2013-07-01 16 views
9

Chcę mieć dostęp do powiązań osoby dzwoniącej. Co jest nie tak?Jak wywołać blok ruby, aby uzyskać dostęp do powiązań z rozmówcami

Dlaczego nie mam dostępu do instancji osoby dzwoniącej w obrębie danego bloku?

+0

Drodzy Downvoter! Jestem tu stosunkowo nowy i byłoby miło uzyskać kilka porad, jeśli moje pytanie nie jest przydatne. :-) Zmieniłem kod zapytania na pełną klasę testową "BlocksTest". Zmieniłem również wywołanie bloku w metodzie 'run' z' @ block.call' na 'instance_eval {@ block.call}', co wywołuje ten sam błąd. – sschmeck

Odpowiedz

4

Wewnątrz bloku nie znajdują się w zakresie np Blocks, więc foo nie jest widoczny. Trzeba przekazać obiekt do bloku jeśli chcesz mieć do niego dostęp:

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

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

Alternatywnie można przekazać bloku do instance_eval:

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

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

Dla różnicy między proc i bloku patrz [this] (http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/) i [this] (http : //net.tutsplus.com/tutorials/ruby/ruby-on-rails-study-guide-blocks-procs-and-lambdas/). – toro2k

+0

Dzięki! Próbowałem drugiego rozwiązania, zanim zadałem pytanie, ale bez operatora '&'. 'instance_eval {@ block.call};' podnosi ten sam błąd. Jaka jest różnica między blokiem a składnią Proc? – sschmeck

+0

Dzięki za linki. Nie znalazłem wyjaśnienia dla różnicy między 'instance_eval (& block)' i 'instance_eval {block.call}'. Pierwszy sposób przekształca Proc do bloku, a drugi tworzy nowy blok i wykonuje Proc. Wciąż nie mam pojęcia, dlaczego wiązania/zakresy podejść różnią się. : - / – sschmeck

0

Próbowano go odtworzyć:

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

Wewnątrz { } lub poza {}, foo nie została zdefiniowana jako method lub varable. Tak więc parser Ruby został zdezorientowany i rzucił błąd.

Teraz patrz:

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

Spróbuj:

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

spróbować tej

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

    def foo; 'foo'; end 
end