Ви можете використовувати блоки для реалізації зворотних викликів, передачі шматків коду і для реалізації ітераторів.
Блоки являють собою прості шматки коду укладені у фігурні дужки або між do... end
{puts «Hello»} # це блок
do #
club.enroll (person) # і це теж
person.socialize #
end #
Коли блок створено його можна асоціювати з викликом методу. Це робиться розміщенням блоку коду в кінці рядка, що містить виклик методу. Наприклад, у наступному коді блок, що містить puts «Hi», асоціюється з викликом методу greet.
greet { puts «Hi» }
Якщо у методу є параметри, вони перераховуються перед блоком:
verbose_greet(«Dave», «loyal customer») {puts «Hi»}
Метод може викликати асоційований блок один або кілька разів використовуючи вираз yield. Воно схоже на виклик методу, який викликає блок, асоційований з методом, що містить yield.
Наступний приклад показує це в дії. Ми визначимо метод який викликає yield два рази. Потім викличемо цей метод, помістивши блок на тій же лінії після виклику (і після перерахування аргументів методу)
def call_block
puts «Start of method»
yield
yield
puts «End of method»
end
call_block { puts «In the block» }
результатом буде:
Start of method
In the block
In the block
End of method
Кожен виклик yield виводить на друк «In the block».
Блок коду можна викликати з параметрами, передаючи їх через yield. Всередині блоку просто перерахуйте аргументи, уклавши їх між вертикальними рисами (|).
def call_block
yield(«hello», 99)
end
call_block {|str, num|}
Блоки коду використовуються всюди для реалізації ітераторів: методи, які повертають елементи послідовності взяті з певної збірки, наприклад, з масиву.
animals = %w( ant bee cat dog elk )
animals.each {|animal| puts animal }
дасть:
ant
bee
cat
dog
elk
Всередині класу Array ми б реалізували ітератор each наступним чином, використовуючи псевдо-код:
# всередині класу Array
def each
for each element # < - псевдо
yield element
end
end
Більшість конструкцій перебору вбудовані в C або Java в Рубі є простими методами, що викликають асоційовані блоки нуль або більше разів.
[ 'cat', 'dog', 'horse' ].each { |name| print name, "" ""}
5.times { print ""*"" }
3.upto(6) { |i| print i }
('a'..'e').each { |char| print char }
в результаті дає нам
cat dog horse *****3456abcde
Ми просимо об'єкт 5 викликати блок п'ять разів і потім просимо об'єкт викликати блок, передаючи послідовні значення поки вони не досягнуть значення 6. І в кінці діапазон величин від a до e викликає блок використовуючи метод each.
Все це - вільний переклад Dave Thomas - Programming ruby 2nd edition (The Pragmatic Programmers'Guide)