homeASCIIcasts

6: Uso de Symbol to_proc para sustituir un bloque 

(view original Railscast)

Other translations: En It Fr

Other formats:

Written by Aldo Escudero (aldoescudero.com.ar)

La extraña sintaxis en la línea del find que vemos debajo, con un ampersand y un symbol, se llama Symbol to_proc y es algo que Rails agrega a Ruby.

class Project < ActiveRecord::Base  
  has_many :tasks  
  
  def self.all_names  
    find(:all).collect(&:name)  
  end  
end  

Utilizaremos script/console de Rails para explicar como funciona. Primero, busquemos un arreglo de Projects.

Laa-Laa:todo eifion$ script/console 
Loading development environment (Rails 2.2.2) 
>> projects = Project.find(:all) 
=> [#<Project id: 1, name: "Write another ASCIIcast", created_at: "2008-12-29 09:32:47", updated_at: "2008-12-29 09:32:47">, #<Project id: 2, name: "Go out walking", created_at: "2008-12-29 09:33:04", updated_at: "2008-12-29 09:33:04">]

Hay dos proyectos y queremos devolver un arreglo de todos los nombres de los proyectos. Una manera de hacerlo sería usando el método collect, que toma un bloque (block), y devuelve el nombre de cada proyecto. El método collect itera a través de un arreglo, ejecuta algún código sobre cada ítem en el arreglo, y devuelve un arreglo que contiene cada resultado del código ejecutado sobre cada ítem en el arreglo original.

>> projects.collect { |p| p.name } 
=> ["Write another ASCIIcast", "Go out walking"]

Symbol to_proc permite utilizar un atajo cuando se desea realizar una llamada a un método contra el objeto que se envía al bloque. Para hacer esto, se le pasa un parámetro que comienza con un ampersand (&) seguido por el nombre del método como símbolo (symbol):

>> projects.collect {&:name} 
=> ["Write another ASCIIcast", "Go out walking"]

Esto es más útil cuando se quiere combinar múltiples llamadas a métodos:

>> projects.collect(&:name).collect(&:upcase) 
=> ["WRITE ANOTHER ASCIICAST", "GO OUT WALKING"]

Esta técnica no se limita al método collect; puede aplicarse a cualquier método que tome un bloque. Por ejemplo, los métodos any? y all? pueden utilizar este atajo para ver si todos (all) o cualquier proyecto (any) son válidos, o incluso para guardar todos nuestros proyectos.

>> projects.all?(&:valid?) 
=> true >> 
projects.any?(&:valid?) 
=> true >> projects.each(&:save!) 
=> [#<Project id: 1, name: "Write another ASCIIcast", created_at: "2008-12-29 09:32:47", updated_at: "2008-12-29 09:32:47">, #<Project id: 2, name: "Go out walking", created_at: "2008-12-29 09:33:04", updated_at: "2008-12-29 09:33:04">]

A pesar de su sintaxis un poco extraña, symbol to_proc es muy útil cuando se necesita encadenar métodos entre sí con bloques.