Block
Блок - это произвольный код, который можно передать любому методу в качестве неявного последнего аргумента. Это конструкция do end. Блок очень похож на функцию, которая передается в функцию times(). Но передается довольно необычным способом. Ключевое слово do начинается после того, как закрыты вызывающие скобки у метода. Блок просто отделяется пробелом от вызова самой функции -
5.times() do |i|
puts i
end
# => 0
# => 1
# => 2
# => 3
# => 4
Блок работает как замыкание, а значит внутри него можно использовать любые переменные, определенные снаружи и выше блока -
name = 'ruby'
3.times do # параметры блока можно опускать
puts name
end
# => ruby
# => ruby
# => ruby
У блоков есть альтернативный синтаксис. Пример выше можно было записать так:
5.times { |i| puts i }Существует два способа выполнить код блока, переданный методу. Ключевое слово yield в теле блока и аргумент &block.
Когда в теле метода вызывается yield, то подразумевается следующее: «отдай управление блоку, а когда тот закончит, верни управление этому методу».
def say_hello
puts "before block"
yield
puts "after block"
end
say_hello { puts "inside block" }
# => before block
# => inside block
# => after block
Но, если не передать блок в метод, то вызов последнего будет выполнен с ошибкой -
def say_hello
puts "before block"
yield
puts "after block"
end
say_hello
# => 'Object#say_hello': no block given (yield) (LocalJumpError)
Чтобы избежать этой ошибки, необходимо удостоверится, что блок был передан с помощью метода block_given?
def say_hello
puts "before block"
yield if block_given?
puts "after block"
end
say_hello
# => before block
# => after block
Второй способ выполнить код блока, использовать аргумент &block
def say_hello(&block)
puts "before block"
block.call
puts "after block"
end
say_hello { puts "inside block" }
# => before block
# => inside block
# => after block