Blocks

Los code blocks son trozos de código que asociamos a invocaciones de métodos, como si fuera un parámetro más.

Es una característica muy poderosa y muy importante de entender, pues es un recurso muy utilizado en Ruby.

Se pueden utilizar code blocks para implementar callbacks, para pasar trozos de código de un lado a otro, y para implementar iteradores.

Un code block es un bloque de código entre llaves o entre los keyword do y end.

# Esto es un code block
{ puts "Hola" }

# Y esto también
do
  club.asociar(persona)
  persona.socializar
end

Hay dos tipos de delimitaciones porque a veces es más natural utilizar uno u otro. Algo recurrente en ruby, proveer diferentes formas para hacer lo mismo.

No obstante, la comunidad utiliza la siguiente convención: utilizar las llaves para bloques de una sóla línea, y do / end para bloques multilínea.

Ejemplo:

# Usamos llaves porque es un bloque de una sóla línea
saludar { puts 'Hola' }

# Si el método necesita parámetros se ponen antes del bloque
saludar("Carlos", "cliente") { puts 'hola' }

Un método puede invocar el bloque una o más veces utilizando el statement yield. Piensa que es algo como una llamada a un método que invoca el bloque asociado con la llamada del método que contiene yield.

Ejemplo:

def llamar_al_bloque
  puts 'Comienza el método'
  yield
  yield
  puts 'Fin'
end

llamar_al_bloque { puts 'En el bloque' }

# Imprime
# Comienza el método
# En el bloque
# En el bloque
# Fin

El código del bloque se ejecuta 2 veces, una por cada yield. Si necesitas pasar argumentos al bloque la sintaxis es la siguiente:

def quien_dice_que
  yield('Carlos', 'hola')
  yield('Miguel', 'adios')
end

# Los argumentos van entre | al inicio del bloque
quien_dice_que {|persona, frase| puts "#{persona} dice #{frase}"}

# Imprime
# Carlos dice hola
# Miguel dice adios

Los code blocks se utilizan también para implementar iteradores, que son métodos que devuelven sucesivamente elementos dealgún tipo de colección, como un array:

# Definimos un array
animales = ["gato", "perro"]

# Ejecuta el bloque una vez por item en el array
animales.each {|animal| puts animal}

# Imprime
# gato
# perro

# Más ejemplos

5.times { print "yo "}
# Imprime yo yo yo yo yo

3.upto(6) {|i| print i}
# Imprime 3456