56

I have trying to access helper methods from a rails 3 mailer in order to access the current user for the session.

I put the helper :application in my mailer class, which seems to work, except the methods defined therein are not available to my mailer (i get undefined errors). Does anyone know how this is supposed to work?

Here's my class:

class CommentMailer < ActionMailer::Base
  default :from => "Andre Fournier <andre@gfournier.com>"

  helper :application
end

Thanks, Sean

Sean O'Hara
  • 1,218
  • 1
  • 11
  • 19
  • Can you also include your code and method definition for getting the current user? – Pan Thomakos Feb 08 '11 at 19:10
  • Sure, here it is (the reference in the mailer): `:from => "#{current_sender.name} <#{current_sender.email}>"` and the definition: `def current_sender current_user end` – Sean O'Hara Feb 08 '11 at 19:15
  • I mean, do you have current_user defined in a helper method or in your application controller and if so, what's the definition? – Pan Thomakos Feb 08 '11 at 19:19
  • In this app current_user is a helper method provided by Devise. However, when I call current_sender, which I defined in my application_helper file, I get an undefined error. The issue is not with current_user because it is never called. – Sean O'Hara Feb 08 '11 at 19:53
  • My suggestion would be to add an alias to current_user from current_sender in your CommentMailer class instead of including the entire helper. If that doesn't work you'll need to make current_user available to your CommentMailer class. It's better to do this since it doesn't require including an entire helper module. – Pan Thomakos Feb 08 '11 at 19:56
  • Thanks. I'll try to find some way of making current_user available to the CommentMailer class, but so far, that is precisely what i've been uable to figure out. – Sean O'Hara Feb 08 '11 at 20:19
  • Why not assigning current_user to an instance variable in your mailer method(s)? `@current_sender = current_user`? Then use the variable within your views. – polarblau Feb 08 '11 at 22:28
  • similar one - http://amolnpujari.wordpress.com/2013/12/27/highlight-changes-being-made-on-activerecord-object-inside-mail/ – Amol Pujari Dec 27 '13 at 11:32

11 Answers11

72

To enable you to access application helpers from the ActionMailer views, try adding this:

add_template_helper(ApplicationHelper)

To your ActionMailer (just under your default :from line).

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
William Denniss
  • 16,089
  • 7
  • 81
  • 124
64

Use helper ApplicationHelper

class NotificationsMailer < ActionMailer::Base

  default from: "Community Point <Team@CommunityPoint.ca>"
  helper ApplicationHelper
  helper NotificationMailerHelper

  # ...other code...

NOTE: These helper methods are only available to the Views. They are not available in the mailer class (NotificationMailer in my example).

If you need them in the actual mailer class, use include ApplicationHelper, like so:

class NotificationMailer < ActionMailer::Base

  include ApplicationHelper

  # ... the rest of your mailer class.

end

From this other SO question.

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • 13
    It's important to know that these helper methods are not available in the mailer class (`NotificationMailer` in my example), but only to the views themselves. If you need them in the mailer class itself, you should be able to use `include ApplicationHelper` instead. – Joshua Pinter Aug 05 '15 at 20:40
25

This is a very old question, but I don't see the full answer, so I will try as I didn't find another resource.

It depends on what you are doing with the methods that have been defined in the helper module. If they are class methods, and everything that's not called on a specific instance seem to be a class methods for 3.2.13, you need to use

extend ApplicationHelper

if an instance methods

include ApplicationHelper

and if you want to use them in a mailer view

helper ApplicationHelper
Questor
  • 313
  • 3
  • 9
  • Thank you for this !!! I have no way of marking this as an answer. - Are the extend / include / helper depreciable , ie using extend covers include and helper ? – Steven Moffat Dec 18 '17 at 14:42
7

You could try mixing in the required helper module:

class CommentMailer < ActionMailer::Base
  include ApplicationHelper
end
dangerousdave
  • 6,331
  • 8
  • 45
  • 62
  • 2
    I'm not sure if this will work from the views. I'm guessing no. But it will definitely work if you want to use the helpers in the mailer class itself. – aNoble May 09 '13 at 15:28
4

Josh Pinter's answer is correct, but I discovered that it is not necessary.

What is necessary is to name the helper correctly.

NotificationMailerHelper is correct. NotificationMailersHelper (note the s) is not correct.

The class and filename of the helper must match and be correctly spelled.

Rails 3.2.2

B Seven
  • 44,484
  • 66
  • 240
  • 385
3

include ActionView::Helpers::TextHelper worked for me in the Mailer controller (.rb file). This allowed me to use the pluralize helper in a Mailer controller action (helpers worked fine from the get go in Mailer views). None of the other answers worked, at least not on Rails 4.2

wetjosh
  • 6,288
  • 4
  • 23
  • 32
2

If you want to call helper method from ActionMailer you need to include helper (module) in Mailer file as, if Helper module name is “UserHelper”, then need to write following in Mailer file

class CommentMailer < ActionMailer::Base
    default :from => "Andre Fournier <andre@gfournier.com>"
    add_template_helper(UserHelper)
end

Or

class CommentMailer < ActionMailer::Base
    default :from => "Andre Fournier <andre@gfournier.com>"
    include UserHelper
end

Hope this is helpful.

PythonDev
  • 4,287
  • 6
  • 32
  • 39
2

The single method version of promoting a method to being a helper that is available in ApplicationController also works in ActionMailer:

class ApplicationMailer < ActionMailer::Base
  helper_method :marketing_host

  def marketing_host
    "marketing.yoursite.com"
  end
end

from there you can call marketing_host from any of your mailer views

stcorbett
  • 613
  • 6
  • 5
0

None of the *_path helpers are accessible by default inside of an email. It is necessary instead to use the *_url form of the wanted helper. So, for instance, instead of using user_path(@user) it is necessary to use user_url(@user). See at Action Mailer basics.

Asarluhi
  • 1,280
  • 3
  • 22
  • 43
0

I'm not sure exactly what you are doing here, but when I want to access current_user from a mailer, I make a mailer method that I pass the user to as an argument:

class CommentMailer < ActionMailer::Base
  default :from => "Andre Fournier <andre@gfournier.com>"

  def blog_comment(user)
    @recipients                   = user.email
    @from                         = "andre@gfournier.com"
    @sent_on                      = Time.now
    @timestamp                    = Time.now
    @user                         = user
  end
end

With the above, @user, as well as all the other instance variables, are accessible from inside the mailer views ./views/comment_mailer/blog_comment.html.erb and ./views/comment_mailer/blog_comment.text.erb

Separately, you can make a helper called

comment_mailer_helper.rb

and put into that helper any methods that you want to be available to your mailer's views. This seems to me more like what you might want, regarding helpers, because helpers are designed to help views, whereas a mailer is analogous to a controller.

fengolly
  • 503
  • 3
  • 8
-4

A hackish means of achieving what I wanted is to store the objects I need (current_user.name + current_user.email) in thread attributes, like so: Thread.current[:name] = current_user.name. Then in my mailer I just assigned new instance variables to those values stored in the thread: @name = Thread.current[:name]. This works, but it won't work if using something like delayed job.

Sean O'Hara
  • 1,218
  • 1
  • 11
  • 19