How to use my view helpers in my ActionMailer views?
Ruby on-RailsRuby on-Rails Problem Overview
I want to use the methods I defined in app/helpers/annotations_helper.rb
in my ReportMailer views (app/views/report_mailer/usage_report.text.html.erb
). How do I do this?
Based on this guide it seems like the add_template_helper(helper_module)
method might do what I want, but I can't figure out how to use it.
(BTW, is there a reason you get access to a different set of helpers in mailer views? This is pretty annoying.)
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
In the mailer class that you are using to manage your emails:
class ReportMailer < ActionMailer::Base
add_template_helper(AnnotationsHelper)
...
end
Solution 2 - Ruby on-Rails
In Rails 3, just use the helper method at the top of your ActionMailer class:
helper :mail # loads app/helpers/mail_helper.rb & includes MailHelper
I just passed in a block, since I only need it in the one Mailer:
helper do
def host_url_for(url_path)
root_url.chop + url_path
end
end
(be sure to set config.action_mailer.default_url_options.)
(and if you use url_for, be sure to pass in :only_path => false)
Solution 3 - Ruby on-Rails
For all mailers in Rails 3 (setting "application" helper):
# config/application.rb:
...
config.to_prepare do
ActionMailer::Base.helper "application"
end
Solution 4 - Ruby on-Rails
For Ruby on Rails 4, I had to do 2 things:
(1) As Duke already said, if the helper you want to add is UsersHelper
for example, then add
helper :users
to the derived ActionMailer
class (e.g. app/mailers/user_mailer.rb
)
(2) After that, I got a new error:
ActionView::Template::Error (Missing host to link to! Please provide the :host
parameter, set default_url_options[:host], or set :only_path to true)
To fix this, add the line
config.action_mailer.default_url_options = { :host => 'localhost' }
to each of the config/environments/*.rb
files. For config/environments/production.rb
, replace localhost
with a more appropriate host for the production helper-generated urls.
Q: For #2, why does the mail view need this information, and the regular views do not?
A: Because the regular views don't need to know the host
, since all generated links are served from the host they link to. Links that show up in emails are not served from the same host (unless you are linking to hotmail.com
or gmail.com
, etc.)
Solution 5 - Ruby on-Rails
(This is an old question but Rails has evolved so I'm sharing what works for me in Rails 5.2.)
Typically you might want to use a custom view helper in rendering the subject line of an email as well as the HTML. In the case where the view helper is in app/helpers/application_helper.rb as follows:
module ApplicationHelper
def mydate(time, timezone)
time.in_time_zone(timezone).strftime("%A %-d %B %Y")
end
end
I can create a dynamic email subject line and template which both use the helper but I need to tell Rails to use the ApplicationHelper explicitly in apps/mailer/user_mailer.rb in two different ways, as you can see in the second and third lines here:
class UserMailer < ApplicationMailer
include ApplicationHelper # This enables me to use mydate in the subject line
helper :application # This enables me to use mydate in the email template (party_thanks.html.erb)
def party_thanks
@party = params[:party]
mail(to: '[email protected]',
subject: "Thanks for coming on #{mydate(@party.created_at, @party.timezone)}")
end
end
I should mention that these two lines work just as well so choose one or the other:
helper :application
add_template_helper(ApplicationHelper)
FWIW, the email template at app/views/user_mailer/party_thanks.html.erb looks like this:
<p>
Thanks for coming on <%= mydate(@party.created_at, @party.timezone) %>
</p>
And the app/controller/party_controller.rb controller looks like this
class PartyController < ApplicationController
...
def create
...
UserMailer.with(party: @party).party_thanks.deliver_later
...
end
end
I have to agree with OP (@Tom Lehman) and @gabeodess that this all feels quite convoluted given https://guides.rubyonrails.org/action_mailer_basics.html#using-action-mailer-helpers so perhaps I am missing something...
Solution 6 - Ruby on-Rails
You can just add in your mailer
helper :application
or whatever helper you need
Solution 7 - Ruby on-Rails
in my case for Rails4, i do like this:
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
add_template_helper ApplicationHelper
...
end
and
# app/mailers/user_mailer.rb
class AccountMailer < ApplicationMailer
def some_method(x, y)
end
end
so that you do not have to specify add_template_helper
everywhere.
Solution 8 - Ruby on-Rails
This is what I did in rails 6
class ApplicationMailer < ActionMailer::Base
default from: '[email protected]'
layout 'mailer'
# Add whatever helper you want
helper :application
end