homeASCIIcasts

6: Shortcut Blocks with Symbol to_proc 

(view original Railscast)

Other translations: It Es Fr

The odd syntax in the find line in the code block below, with the ampersand and symbol, is called Symbol to_proc and is something that Rails adds to Ruby.

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

We’ll use Rails’ script/console to explain how it works. First, let’s get an array of 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">]

There are two projects and we want to return an array of all of the project names. One way to do that would be to use the collect method, which takes a block, and return the name of each Project. The collect method iterates through an array, executes some code against each item in the array, and returns an array containing each result of the code executed against each item in the original array.

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

Symbol to_proc allows you to use a shortcut when you want to perform a method call against the object that is sent to the block. To do this you pass a parameter that starts with an ampersand followed by the name of the method as a symbol:

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

This becomes more useful when you want to combine multiple method calls:

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

This technique isn’t restricted to the collect method; it can be applied to any method that takes a block. For example the any? and all? methods can use this shortcut to see if all or any of out projects are valid, or even to save all of our projects.

>> 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">]

Despite its slightly odd syntax, Symbol to_proc is well worth using when you have to string methods together with blocks.