0

I'm passing a method from one class to another.

#!/usr/bin/env ruby

class A
  def m
    p self
  end
end

class B
end

B.define_method :m, &A.new.method(:m)
B.new.m # => #<A:0x00007fb28903e3f8>

Why is the method still related to A, not to B? How can i achieve this?

CroneKorkN
  • 33
  • 1
  • 5
  • 3
    owner of an instance method cannot be changed, it will still remain with class `A`. `A.new.method(:m) #=> A` – kiddorails Jun 18 '18 at 17:20
  • 3
    I checked around if that could be done by `unbind`ing the method, but the method sticks to the closure it's defined in. - https://stackoverflow.com/questions/34844833/what-the-purpose-of-bind-unbind-methods-in-ruby – kiddorails Jun 18 '18 at 17:27
  • @kiddorails Theres absolutely no way to copy a method around? Why should it be called "define_method", if it only defines a references (in this case)? – CroneKorkN Jun 18 '18 at 17:32
  • 3
    In this case, `define_method` is **creating** the method, but you are still passing the proc of `A#m`. B's new method remains like a proxy method in that case. You can even define it with `B.define_method(:my_method, &A.new.method(:m); B.instance_method(:my_method).owner #=> B` – kiddorails Jun 18 '18 at 17:34
  • So, i'm afraid my approach of evaluating user defined dsl-code by first collecting it within a kind of sandbox und then pass the methods around to their final places is not realizable in ruby. – CroneKorkN Jun 18 '18 at 17:42
  • 1
    you can have the methods be defined in a `module` and then include that module in your `sandbox`, that way you maybe able to sandbox the external dsl-code. Let's wait for some other answers; if there is a way, I'm sure the community will come up with it :) – kiddorails Jun 18 '18 at 17:46
  • 1
    `define_method` is private so your current example would result in a `NoMethodError private method \`define_method' called for B:Class` not sure what you are trying to accomplish with `B` but `B = Class.new(A)` would result in `B.new.m #=> #` via inheritance – engineersmnky Jun 18 '18 at 18:18
  • @engineersmnky I am writing a server config management tool. Users can define nodes (node "example.com" do ... end) and capabilities (def apt install: nil ... end) within their project-directory. As i dont know, which user-provided-file will contain a capability-definition, i need to preevaluate all files and pass the node-definitions (technically method calls) to one and the capability-definitions (tachnically method definitions) to another place after that. https://github.com/CroneKorkN/rbcm/blob/stackoverflow_rebind_method/lib/project_file.rb – CroneKorkN Jun 18 '18 at 18:41
  • 1
    You can unbind and rebind to `B` if `class B < A` – iCodeSometime Jun 18 '18 at 20:24
  • I am now parsing each user provied file two times. Once for catching method calls, ones for catching method definitions. I am using a module for the latter one, so i get unbound methods that can be bound to any class: https://github.com/CroneKorkN/rbcm/blob/59d874262ca6a6f8f49d9767021dcc7d20eed262/app/project/file.rb#L10-L18 – CroneKorkN Jun 19 '18 at 09:09
  • @kiddorails and others: guys, could you please compose comments as answer - it looks like big and helpful article! – Pavel Mikhailyuk Jun 19 '18 at 10:25

0 Answers0