Mam metodę, którą chcę inaczej działać w zależności od scenariusza, więc chcę móc przekazać blok do metody i wykonać, jeśli blok zostanie podany.
Jestem jednak zdezorientowany przez zakres zmiennej w bloku, przez który przechodzę.
Na przykład:
def original_method (a, b, opt = {id: nil, id_map: {}})
element_id = (opt[:id_map])
yield if block_given?
end
I nowa metoda, która przechodzi przez blok:
def new_method(a, b, opt)
original_method (a, b, opt) do
if(element_id.include? "some text")
puts "it has some text"
end
end
end
Ale pojawia się błąd:
undefined local variable or method `element_id"
na linii podziału.
Czy można to zrobić?
Odpowiedzi:
5 dla odpowiedzi № 1Musisz przekazać lokalną zmienną element_id
, tak jak yield
s argument.
def original_method (a, b, opt = {id: nil, id_map: {}})
element_id = opt[:id_map]
yield(element_id) if block_given? # pass it as argument
end
Następnie zaakceptuj to tak:
def new_method(a, b, opt)
original_method (a, b, opt) do | element_id | # receive as block pramater
if(element_id.include? "some text")
puts "it has some text"
end
end
end
element_id
zmienna lokalna została utworzona wewnątrz metody original_method
, dlatego jest dostępna tylko w tej metodzie.
Wewnątrz metody new_method
, gdy wywołujesz metodę original_method
z a blok dołączone do niego, ze względu na zamknięcie możliwość ma dostęp do wszystkich zmiennych w metodzie new_method
od początku do punktu, w którym blok jest tworzony.
1 dla odpowiedzi nr 2
Odpowiedz na swoje pośrednie pytanie:
Bloki mają zasięg leksykalnie, co oznacza, że mają dostęp do zmiennych z zakresu, w którym zostały zdefiniowane (w przeciwieństwie do "używanych w").