2013-04-22 5 views
1

코드 블록 instance_exec을 취하여 적절한 결과를 얻을 수 있습니다. 다른 객체에서 메서드를 가져와 내 범위에서 메서드 중 하나를 호출하고 싶습니다. 다른 객체에서 메서드를 가져 와서 proc으로 변환 한 다음 instance_exec으로 예상 한 결과를 얻지 못합니다. 코드는 다음과 같습니다.instance_exec를 사용하여 메소드를 Proc로 변환

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 

답변

1

따라서 .to_proc을 호출하면 원래 구현의 바인딩이 유지되고 다시 바인딩 할 수 없습니다. 글쎄, 당신은 할 수 있지만 오직 첫 번째와 같은 유형의 객체에 대해서만 가능합니다. 상속을 통해 약간의 열정을 나타낼 수는 있지만, 그렇게 생각하지는 않습니다.

솔루션은 메소드를 사용하는 대신 실제 변수 Proc을 변수에 넣고 실행 시간까지 바인딩되지 않으므로 변수를 사용합니다.

0

이 얼마나 아이디어의 좋은하지 않도록,하지만이 테스트를 통과 : 루비, 메소드가있는 클래스에 영구적으로 결합되어 def some_method를 사용하여 정의, 보인다

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 
+0

그래, 나는 eval을 사용하지 않는 편이 좋을 것이다. 대신 코드 블록을 사용할 수 있습니다. – BeepDog