I was recently reminded of this piece of syntax:
ids = users.collect(&:user_id)
This is equivalent to:
ids = users.collect { |u| u.user_id }
The implementation is provided by a Rails extension to Ruby’s Symbol class and hence is not available in pure Ruby environments, like irb.
While clearly this is a handy shortcut, it makes your code quite unreadable for anyone who doesn’t understand the to_proc extension made by the Rails team—it is not inherently obvious what you’re doing. If your code is being maintained by multiple developers, is it really wise to use it?
For those of you wondering how this little trick works: the Rails team is exploiting the nature of duck typing in Ruby. When the & operator is used as a function parameter, you are telling Ruby to treat that parameter as the block passed to the function. In order to assure that the object is a Proc object, Ruby calls to_proc on all such parameters. Hence, the Symbol class has been extended by the Rails team to include a to_proc method. This method returns a Proc which calls the method by the same name as the symbol itself.




August 30th, 2006 at 10:06 AM Hi JD, I'm so glad to see you post this. I was wondering if I was the only one who thought this was a bit of an ugly hack. Something makes me definitely uneasy about it, in ways that other Ruby syntactical sugar doesn't. I could see it being useful, but it just doesn't seem "conceptually appropriate." Given how much attention has been paid to readability in Ruby and Rails, I wonder what the point of making this one aberrant hack was.
October 17th, 2006 at 05:28 AM Hi jd, I kinda agree with you that it shouldn't be in Rails. It was cool hackery when first introduced but at what cost to understanding the code? Bob
November 15th, 2006 at 10:37 AM Why couldn't they implement something like the following instead? StupidUsers.each.destroy It would be harder to do, but it would make much more sense, semantically than: StupidUsers.each(&:destroy) There's probably some technical hurdle I'm not seeing here, but couldn't one just rewrite each to proxy whatever method you're sending it over to every object in the collection? It definitely would follow Matz's putative "principle of least surprise":http://www.artima.com/intv/rubyP.html.
May 3rd, 2007 at 12:45 AM Newbie here, but now newbie to the article!
May 3rd, 2007 at 12:50 AM test
May 3rd, 2007 at 01:43 AM sex