This post originated from an RSS feed registered with Ruby Buzz
by john hume.
Original Post: Loving to_proc
Feed Title: El Humidor
Feed URL: http://feeds.feedburner.com/ElHumidor
Feed Description: John D. Hume on Ruby and development with agile teams.
Anytime I'm pairing with a developer who isn't familiar with ActiveSupport's Symbol#to_proc extension, it's fun to see their reaction when they see how it works. It's the most radical example I've seen of a simple (and pure-Ruby) extension to a core class allowing for awesome improvements in readability.
The one frustrating thing about it is that it's so limited: you can only send one method with no arguments to each yielded object. If you need to pass arguments or do any more complex calculation, you're back to passing an associated block the old-fashioned way.
A couple of weeks ago Patrick and I were pairing and noticed a beneficial side-effect of the limitations of Symbol#to_proc: sometimes when you can't use it right off the bat, it's because the behavior you were going to put in the block would be better off living in the objects you're working with.
Here's a simple example. Imagine you want to expose the area codes represented in a collection of phone numbers. Your initial implementation might look like this.
defarea_codesself.phone_numbers.collect do |phone_number|
phone_number[0..2]end.uniq
end
"Shame that block's so ugly," you might think. Well you're right! It is a shame, and it doesn't have to be that way. It's ugly because it knows about the guts of phone numbers. If phone numbers knew more about themselves, using them could be prettier.
defarea_codesself.phone_numbers.collect(&:area_code).uniq
end
Of course sometimes you really need to pass arguments. We toyed around with introducing an Array#to_proc that looked like this.
In the end we decided that, while nicely brief, it wasn't pretty enough to put into our code base -- too much punctuation -- and stuck with the old-fashioned way.
Are there any other core extensions that have really floated your boat? Do share.