Mapping Object Values With Ruby's Ampersand-symbol Technique
Discovered another little Ruby nugget the other day. The nugget gives a shorter syntax when you want to map the return value of a message sent to a list of objects, say, the name of the class of the object. In the past I would use Array#map
to produce the list with something like:
objects = [1, :number_1, "1"]
classes = objects.map { |o| o.class }
classes.inspect
# => [Fixnum, Symbol, String]
Turns out that Ruby has a shortcut that shortens your keystrokes a bit:
objects = [1, :number_1, "1"]
classes = objects.map(&:class)
classes.inspect
# => [Fixnum, Symbol, String]
The two snippets are functionally identical. By passing a symbol to map preceded by an ampersand, Ruby will call Symbol#to_proc
on the passed symbol (e.g. :class.to_proc
), which returns a proc object like {|o| o.class }
. Where would you use this you ask? The day I learned this little ditty I was writing some tests that were verifying some active record associations. Whenever I needed to update values on a has_many
collection for a particular model, I actually needed to assert that the associated collection of objects were rebuilt with the new values, deleting the old rows and recreating new ones. The ampersand-symbol technique above was nice for this.
describe Father do
it 'should create new children when I attempt to update the children' do
father = Factory(:father)
orig_children = father.children.map(&:id)
# perform the update method
father.reload
father.children.map(&:id).should\_not == orig\_children
end
end
So I thought I’d pass the word on. Cool stuff in Ruby. Who knew?