For a long time there was no good way to generate a URL within an ActionMailer. If you wanted to send a registration email when a user signs up for your application you would have had to pass in the url to be included in the email:
class MyController < ApplicationController
def register
# .. registration logic ...
UserMailer.deliver_registration(user, home_url)
end
end
class UserMailer < ActionMailer::Base
def registration(user, url)
@body = { 'user' => user, 'home' => url }
end
end
This is hardly a hack, but it’s not as nice as it could be. It would be nice if the mailer itself could generate the url – or perhaps if the email template itself could generate the url? That day has come with the new ActionController::UrlWriter module.
Just include ActionController::UrlWriter in your mailer and you get access to all the familiar url_for and even the named url methods (home_url in this example):
class UserMailer < ActionMailer::Base
include ActionController::UrlWriter
def registration(user)
@body = { 'user' => user, 'home' => home_url }
end
end
tags: rails, rubyonrails, ActionMailer

I think it’s ridiculous that Mailers are treated liek model objects. They are controllers plain and simple. They control the logic of generating the mailer view. As such they need power to call all things a normal controller does..there need to be built in view helpers, url generation, named routes, etc. Why we have to go through convoluted maneuvers to get this to work doesn’t seem right. Mailers are underdeveloped in rails. There is a nice mailer layout plugin out there now finally that lets you do the most common sense thing for emails…have a common layout. Please rails gods, spend some more time on the mailers and make them into full citizens of railsville :-)
“They are controllers plain and simple.”
Well, it is really no more of a controller than ActiveRecord is. AR creates a SQL “view” and if you want to include a URL in that SQL statement you have to jump through the exact same hoops as ActionMailer to get it there.