Loving to_proc
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.
[If you're not familiar with the method, read about it here or here. For a bizarre step beyond (that I'm not personally fond of) take a look at this old Dr. Nic post.]
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.
self.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.
self.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.
Array.class_eval do
lambda {|target| target.send *self}
end
end
[1,2,3,4,5].select &[:between?, 2, 4] # => [2, 3, 4]
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.