Quantcast

One thing I hate about Rails ...

February 26th, 2008

One thing I truly hate in Rails is ActionMailer. It sucks.

First off (admittedly a minor point), mailers are stored in app/models, even though they are basically a pseudo controllers, complete with view templates (stored in app/views). It makes no sense.

Secondly, ActionMailer does not have access to named routes or any view helpers. The 'rails way' would be to call the mailer from a controller, passing the URL as an argument which is just stupid in my opinion. Most of the time I send an email in an application it is due to a change in an model's state, not due to a specific controller interaction. A nice way of doing this through use of active record observers (which also don't have access to routes).

This means I generally end up hardcoding the URLs in the mailer. It wouldn't be a huge deal if my test coverage checks that the hardcoded url in the email body matches a generated one. But to do that you'll need to write integration tests rather than the default 'ActionMailer' tests that are auto generated. The whole mess frustrates me unlike anything else in Rails.

Merb seems to get it right with its Merb::MailController. Perhaps something similar could be added to Rails via a plugin?

8 Responses to “One thing I hate about Rails ...”

  1. silson Says:
    dude then just write your own. Ruby has rmail and tmail, both of which are solid libraries for mail handling. I have written my own stuff based on rmail a few times b/c ActionMailer is pretty much only for fairly narrow purposes... hence the idea of an opinionated framework.
  2. Wesley Moxam Says:
    silson: I'm considering it. However it's not a matter of ActionMailer being 'opinionated', or it being designed for 'narrow purposes', its that it's just plain poorly thought out. Most of rails makes me happy, this is the one area that makes me angry.
  3. Eric Anderson Says:
    I think it actually makes sense for a mailer to be in the models. But I can see how other people might have an different opinion. As for the helpers most helpers are ok to run in ActionMailer. The only ones that are not are out-of-the-box are the url-based ones. This is because a Mailer may be executed outside of the context of a request (such as a cron job). Without a request there is no way to know the full URL. One way around this is to use default_url_options. I think you can even set it in a before_filter from your controller so that way by the time it get's to your mailer model it will know the correct host without having to be told. Of course you will still want a sane default in case the mailer is called outside of the controller still. I'm not saying that ActionMailer couldn't use some improvement. But it still much better than most systems which usually have VERY primitive mail handing by default (i.e. PHP, etc.)
  4. Chris Bailey Says:
    You could also take a look at Mailfactory, a gem that makes mail easy: http://rubyforge.org/projects/mailfactory/
  5. rick Says:
    Someone to bring some much-needed love to ActionMailer would be *very* welcome. I'd probably do that before starting from scratch. You can also include ActionController::UrlWriter into your action mailers. I think you have to set default_url_options[:host] though.
  6. Nick Kallen Says:
    There's a plugin I wrote called Retardase Inhibitor that makes it possible to generate absolute URLs in ActionMailer templates without setting default URL options
  7. Brad Ediger Says:
    UrlWriter has been included in ActionMailer since AM 1.3.0 (Jan 16, 2007): http://api.rubyonrails.org/files/vendor/rails/actionmailer/CHANGELOG.html. I'm not sure if it included access to named routes back then, but it sure does now.
  8. Wesley Moxam Says:
    rick: thanks, that really helps. I totally missed that.

Sorry, comments are closed for this article.