Использование instance_exec и преобразование метода в Proc
Я могу взять блок кода, instance_exec
это, и получить правильный результат. Я хотел бы снять метод с другого объекта и вызвать один из его методов в моей области видимости. Когда я беру метод из другого объекта, превращаю его в процесс, а затем instance_exec
это, я не получаю ожидаемый результат. Кодекс следует.
class Test1
def ohai(arg)
"magic is #{@magic} and arg is #{arg}"
end
end
class Test2
def initialize
@magic = "MAGICAL!"
end
def scope_checking
@magic
end
def do_it
ohai = Test1.new.method(:ohai)
self.instance_exec("foobar", &ohai)
end
end
describe "Test2 and scopes" do
before do
@t2 = Test2.new
end
it "has MAGICAL! in @magic" do
@t2.scope_checking.should == "MAGICAL!"
end
# This one fails :(
it "works like I expect converting a method to a proc" do
val = @t2.do_it
val.should == "magic is MAGICAL! and arg is foobar"
end
it "should work like I expect" do
val = @t2.instance_exec do
"#{@magic}"
end
val.should == "MAGICAL!"
end
end
2 ответа
Похоже, что в Ruby методы определены с использованием def some_method
постоянно связаны с классом, в котором они определены.
Итак, когда вы звоните .to_proc
на них они сохраняют привязку их первоначальной реализации, и вы не можете их привязать. Ну, вы можете, но только для объекта того же типа, что и первый. Возможно, я мог бы сделать некоторые фантазии с наследованием, но я так не думаю.
Решение становится вместо использования методов, я просто ставлю актуальный Proc
s в переменные и используйте их тогда, поскольку они не связаны до времени выполнения.
Не уверен, насколько это хорошая идея, но это проходит ваши тесты:
class Test1
def ohai(arg, binding)
eval('"magic is #{@magic} "', binding).to_s + "and arg is #{arg}"
end
end
class Test2
def initialize
@magic = "MAGICAL!"
end
def scope_checking
@magic
end
def get_binding
return binding()
end
def do_it
self.instance_exec(get_binding) {|binding| Test1.new.ohai("foobar", binding) }
end
end