ActionMailer pass local variables to the erb template

11,016

Solution 1

All options available in the mail method can be found at http://api.rubyonrails.org/classes/ActionMailer/Base.html#method-i-mail.

We know that render has a :locals option. However we can see that there is no :locals option available for mail. Therefore, no, there is no better way than to use instance variables (unless you want to use something hideous like globals or persistent database objects - don't do this).

Instance variables are what you are meant to use.

Solution 2

As ronalchn pointed out, it's the render that has :locals, not the mail method. So, you need a direct access to the render method in order to pass the locals.

You can give a block to the mail and that way gain access to the render method, something like this:

mail(to: "[email protected]", subject: "Test passing locals to view from mailer") do |format|
  format.html {
    render locals: { recipient_name: "John D." }
  }
end

And now you should be able to use "Hello <%= recipient_name %>"

Solution 3

In Rails 5, you simply have to define instance variables using @ in your method. You no longer have access to the locals property for this purpose.

class UserMailer < ApplicationMailer

  def welcome_email(user_id:, to_email:, user_full_name:, token:)    
    # Mail template variables
    @user = User.find_by(id: user_id)
    @token = token

    mail(:to => to_email,
       :subject => MAILER_SUBJECTS_WELCOME,
       :template_path => "user_mailer",
       :template_name => "welcome_email")
  end
end

Then you can just access them in your email template using <%= @user %> and <%= @token %>

Share:
11,016

Related videos on Youtube

Dmitri
Author by

Dmitri

Updated on June 24, 2022

Comments

  • Dmitri
    Dmitri almost 2 years

    I know I could define instance variables e.g:

    def user_register(username, email)
      @username = username
      @email = email
    
      mail(:to => email, :subject => "Welcome!", :template_name => "reg_#{I18n.locale}")
    end
    

    But, is there a way to use local variables instead, just like passing :locals to partials?

  • Dmitri
    Dmitri over 9 years
    Thank you, @rap1ds I will try that approach :)
  • Leo Lei
    Leo Lei about 6 years
    This has always been the case even prior to Rails 5.