2013-07-01 31 views
9

Tôi muốn có quyền truy cập vào các ràng buộc của người gọi. Có gì sai ở đây?Cách gọi một khối ruby ​​để có quyền truy cập vào các ràng buộc người gọi

require 'test/unit' 

class BlocksTest < Test::Unit::TestCase 

    class Blocks 
    def initialize(&block); @block = block; end 
    def run; instance_eval { @block.call }; end 

    def foo; 'foo'; end 
    end 

    def test_say_foo_via_string 
    assert_equal('foo', Blocks.new{ 'foo' }.run) 
    end 
    # => successful 

    def test_say_foo_via_caller_method 
    assert_equal('foo', Blocks.new{ foo }.run) 
    end 
    # => NameError: undefined local variable or method `foo' 

end 

Tại sao tôi không có quyền truy cập vào cá thể người gọi trong khối đã cho?

+0

thân mến Downvoter! Tôi tương đối mới ở đây và nó sẽ được tốt đẹp nhận được một số lời khuyên nếu câu hỏi của tôi là không hữu ích. :-) Tôi đã thay đổi mã câu hỏi thành một lớp thử nghiệm hoàn chỉnh 'BlocksTest'. Tôi cũng đã thay đổi lệnh gọi khối trong phương thức 'run' từ' @ block.call' thành 'instance_eval {@ block.call}', nó làm tăng cùng một lỗi. – sschmeck

Trả lời

4

Bên trong khối bạn đang không ở trong phạm vi của Blocks dụ, vì vậy foo là không nhìn thấy được. Bạn phải vượt qua các đối tượng để các khối nếu bạn muốn được tiếp cận với nó:

class Blocks 
    # ... 
    def run 
    @block.call(self) 
    end 
    # ... 
end 

blk = Blocks.new { |b| b.foo } 
blk.run 
# => "foo" 

Hoặc bạn có thể vượt qua các khối để instance_eval:

class Blocks 
    # ... 
    def run 
    instance_eval(&@block) 
    end 
    # ... 
end 

blk = Blocks.new { foo } 
blk.run 
# => "foo" 
+0

Đối với sự khác biệt giữa một proc và một khối xem [this] (http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/) và [this] (http : //net.tutsplus.com/tutorials/ruby/ruby-on-rails-study-guide-blocks-procs-and-lambdas/). – toro2k

+0

Cảm ơn! Tôi đã thử giải pháp thứ hai trước khi tôi hỏi câu hỏi nhưng không có toán tử '&'. 'instance_eval {@ block.call};' tăng cùng một lỗi. Sự khác nhau giữa khối và cú pháp Proc là gì? – sschmeck

+0

Cảm ơn các liên kết. Tôi đã không tìm thấy một lời giải thích cho sự khác biệt giữa 'instance_eval (& block)' và 'instance_eval {block.call}'. Cách đầu tiên chuyển đổi các Proc thành một khối và thứ hai tạo ra một khối mới và thực hiện các Proc. Tôi vẫn không có ý tưởng tại sao các ràng buộc/phạm vi của các phương pháp tiếp cận khác nhau. : - / – sschmeck

0

Cố gắng tái tạo nó:

3.times.map{ foo } 
#~> undefined local variable or method `foo' for main:Object (NameError) 

Bên { } hoặc ngoài {}, foo chưa được định nghĩa là một method hoặc varable. Do đó, trình phân tích cú pháp của Ruby bị nhầm lẫn và ném lỗi.

Bây giờ xem:

foo = 12 
3.times.map{ foo } 
# => [12, 12, 12] 

Hãy thử:

test "say method_foo" do 
    assert_equal('foo', Blocks.new{|i| i.foo }.run) 
end 
0

thử này

class Blocks 
    def initialize(&block); @block = block; end 
    def run; instance_eval &@block; end 

    def foo; 'foo'; end 
end 
Các vấn đề liên quan