slammin’ extensions
One of the cooler things about Ruby is the way you can extend objects with methods for a specific case. It really makes you feel like you’re slinging code, rather than just organising objects. Rails makes really good use of this ability with Association extensions.
Association extensions allow you to do cool things like:
has_many :messages do
find(:all).read!
end
end
end
So now you can set all the messages for a particular person as “read” by calling:
oliver.messages.mark_as_read!
Cool, huh? (There’s more in the documentation if you’re interested).
A common antipattern I see is something like the following:
oliver.add_message!( new_message )
Being called to add a new message onto a Person’s “messages” association, when you’ve got some extra logic in add_message! which the default ActiveRecord “<<" method doesn't do for you. For example, you might need to send an email to notify the user they've got new messages.
Hey man, don’t forget the slam operator!
a = []
a << 1 << 2 << 3
puts a
#=> [1, 2, 3]
Well, I call it the “slam” operator, but it’s more correctly called the “push” operator. Or the bitwise left shift, depending on what kind of object you’re calling it on. Slam sounds way cooler though.
You can use the slam operator for your association extensions like this:
has_many :messages do
new_message
returning proxy_owner.messages do |m|
m.add_message!(new_message)
end
end
end
end
oliver.messages << a_brand_new_message
Super cool! You could also move the add_message! logic inside that extension, or make it private - force everyone to use the slam!
(PS. “proxy_owner” refers to the owner of the association - in this example, “oliver”. We use that “returning” block so that the << method returns the proxy_owner's messages collection and behaves like the same method on Array. It also means we can chain slams! CH-CH-CHAIN SLAM!)
(PPS. Don’t forget Assocation Callbacks - like :after_add or :before_add - for simple cases :) Don’t get complex unless you’ve got to!)







Nik Wakelin
Oliver Clarke