使用instance_exec并将方法转换为Proc

时间:2013-04-22 01:43:23

标签: ruby metaprogramming ruby-1.8 ruby-1.8.7

我可以使用一段代码instance_exec,然后获得正确的结果。我想从一个不同的对象中取出一个方法,并在我的范围内调用其中一个方法。当我从另一个对象中获取方法时,将其转换为proc,然后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 个答案:

答案 0 :(得分:1)

似乎在Ruby中,使用def some_method定义的方法永久绑定到它们所定义的类中。

因此,当您对它们调用.to_proc时,它们会保留原始实现的绑定,并且您无法重新绑定它们。好吧,你可以,但只能找到与第一个类型相同的对象。我可以用继承做一些幻想,但我不这么认为。

解决方案不是使用方法,而是将实际的Proc放入变量中然后使用它们,因为它们在执行时间之前不会被绑定。

答案 1 :(得分:0)

不确定这是一个多么好的想法,但这会通过你的测试:

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