Helping out ActionMailer
by Sean Cribbs
ActionMailer is the “red-headed step-child” of Rails. Is it a model?
Is it a view? Is it a controller? It’s really none of the above, but
sits in no-man’s land. In addition it’s usage pattern is kind of
strange, you call the class with
deliver_ in front of
the method name that represents the message you want to send!
That craziness aside, I encountered a particular problem today that
ActionMailer made rather opaque. The solution is a peek at how you
can bend Rails to your will using the power of Ruby. GiftLasso has
some frequently used helpers in the view that generate parts-of-speech
(primarily pronouns) based on the gender of the person in question. I
lumped them all in a helper called, conveniently,
I wanted to make use of these in my
ActionMailer class so we can say
things like “Joe added an iPod to his wishlist” or “Jane purchased a
shirt for herself”.
Naturally, I thought, “The
ActionMailer views should have access to
methods on the class generating them. So I’ll include the helper.”
No dice. Unit tests failed left and right. Whenever it doesn’t “just
work”, I head to the source. How better to determine how it works?
ActionMailer::Base, I found this snippet at the
Aha! So it actually uses
ActionView! That’s our attack point.
Now the first temptation would be to open
ActionView::Base and muck
around with it, but I don’t want to break anything that the
controllers depend on. Luckily, Ruby has the ability to extend the
class of an instantiated object (aka the singleton class). We also
have at our disposal the beautiful
ActiveSupport. So what we’ll do is intercept the creation of the
ActionView object and extend it before it renders anything. Here’s
what I came up with:
You can use this technique to add any helpers you want to ActionMailer.