Something that might have slipped your radar in your Ruby readings is Symbol#to_proc, something that’s been in Rails since 0.14.4.
Using this nice little tidbit of Ruby tricky you can simplify code such as:
articles.collect { |a| a.title }
articles.sort { |a| a.created_at }
to
articles.collect(&:title)
articles.sort(&:created_at)
…and just in case you’re wondering why &:ruby_is_the_new_black doesn’t work in the beautiful ruby shell script you just wrote, it’s because Symbol#to_proc isn’t a standard Ruby thang. To quote Mauricio Fernandez who noted it’s recent inclusion in the upcoming Ruby 1.9:
Symbol#to_proc: first discovered by some anonymous Japanese Rubyist (fairly certain), rediscovered by Florian Groß (I saw that happen back when I wasted my time on #ruby-lang), then popula rized by Pragdave and Rails, finally adopted officially. It’s been a long journey.
“That’s nice,” you say, “but I still don’t really understand what all this Proc and block stuff is about.” Well, let me indulge you in some Ruby block mumblings.
I think the best way to describe a block if you’ve come from web-design-land is to think of it like an anonymous function in Javascript.
For example, the following piece of Ruby:
socceroos.each do |s|
s.congratulate
end
is the equivalent to the following Javascript:
socceroos.each(function(s) {
s.congratulate();
})
The block passed to a function is signified by an ampersand:
class Team
def each(&block)
for player in @players
block.call(player)
end
end
end
In fact, the above pattern of calling the block is so common Ruby takes it one step further, allowing you to simply write:
class MyTeam
def each
for member in @members
yield member
end
end
end
yield member is another way of saying “call the associated block passing it the member”. You don’t even need to add &block to the parameter list.
You would have seen this pattern when dealing with ActiveRecord. The ActiveRecord::Base class allows you to specify a block when creating new instances. For example, if Player was an ActiveRecord subclass you could do the following:
@player = Player.new do |p|
p.name = "Ronaldo"
p.nickname = "Porky"
end
How does ActiveRecord provide this neat API? Easy! It just checks whether you specified a block and, if so, calls the block, passing the new Player object to it.
The bare minimum logic to accomplish this would be:
class ActiveRecord::Base
def initialize
yield self if block_given?
end
end





June 20th, 2006 at 3:57 am
Is this the code for symbol#to_proc, or is there a more general version?
class Symbol def to_proc proc {|o| o.send(self)} end endJune 20th, 2006 at 4:16 am
Fenrir2, that’s just about it. You gotta take into account whether the proc invoker will pass in arguments:
See PragDave’s article on it as well as the latest version that’s included with Rails.
July 14th, 2006 at 2:16 pm
[…] Symbol.to_proc […]
March 12th, 2007 at 1:14 am
Ne v dengah ne v muzejnoj pyli