Rails mailer views in separated directory

Go To StackoverFlow.com

24

I have small organizatoric issue, in my application I have 3 mailer User_mailer, prduct_mailer, some_other_mailer and all of them store their views in app/views/user_mailer ...

I will want to have a subdirectory in /app/views/ called mailers and put all in the folders user_mailer, product_mailer and some_other_mailer.

Thanks,

2012-04-04 19:24
by Calin


21

I so agree with this organization strategy!

And from Nobita's example, I achieved it by doing:

class UserMailer < ActionMailer::Base
  default :from => "whatever@whatever.com"
  default :template_path => '**your_path**'

  def whatever_email(user)
    @user = user
    @url  = "http://whatever.com"
    mail(:to => user.email,
         :subject => "Welcome to Whatever",
         )
  end
end

It is Mailer-specific but not too bad!

2013-09-02 18:32
by Augustin Riedinger
default template_path: "mailers/#{self.name.underscore}". In given example, it would look for templates in: /app/views/mailers/user_mailer/Milovan Zogovic 2014-02-17 09:55
Looks nice. I may change this - Augustin Riedinger 2014-02-17 11:46
Woah! @faraz's answer is even better! : - mltsy 2016-10-21 19:17
This can be done once in ApplicationMailer instead, see @vemv answe - Oded Niv 2018-02-03 11:29
Using Rails 3? I'll update the answe - Augustin Riedinger 2018-02-04 09:58


19

You should really create an ApplicationMailer class with your defaults and inherit from that in your mailers:

# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  append_view_path Rails.root.join('app', 'views', 'mailers')
  default from: "Whatever HQ <hq@whatever.com>"
end

# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  def say_hi(user)
    # ...
  end
end

# app/views/mailers/user_mailer/say_hi.html.erb
<b>Hi @user.name!</b>

This lovely pattern uses the same inheritance scheme as controllers (e.g. ApplicationController < ActionController::Base).

2015-04-22 18:27
by fny
See http://www.rubydoc.info/docs/rails/ActionView/ViewPaths/ClassMethods#appendviewpath-instance_metho - mltsy 2016-10-21 19:18
This is better in design than the accepted answer of setting template path on every mailer, but it doesn't handle lazy locale lookup. @vemv answer is the bes - Oded Niv 2018-02-03 11:29
Can you clarify? I've been using this with different locales for years now without any problems - fny 2018-02-04 17:55


12

I had some luck with this in 3.1

class UserMailer < ActionMailer::Base
  ...
  append_view_path("#{Rails.root}/app/views/mailers")
  ...
end 

Got deprecation warnings on template_root and RAILS_ROOT

2012-06-05 04:39
by pagetribe
Works for me in Rails 3.2.3 - JellicleCat 2012-06-05 21:21
Worked for me in Rails 4. - jstim 2014-04-29 21:55
append_view_path Rails.root.join('app', 'views', 'mailers')Aliaksandr 2015-04-05 13:38
prepend_view_path is probably better so the view lookup code doesn't have to look through all other directories before coming to the mailer-only directory to find the template - siannopollo 2018-05-21 02:09


9

If you happen to need something really flexible, inheritance can help you.

class ApplicationMailer < ActionMailer::Base

  def self.inherited(subclass)
    subclass.default template_path: "mailers/#{subclass.name.to_s.underscore}"
  end

end
2015-10-23 22:28
by vemv
wow. this the best possible answer - Alex V 2017-04-02 20:50
Exactly, append_view_path doesn't handle lazy locale looku - Oded Niv 2018-02-03 11:27


4

You can put the templates wherever you want, but you will have to specify it in the mailer. Something like this:

class UserMailer < ActionMailer::Base
  default :from => "whatever@whatever.com"

  def whatever_email(user)
    @user = user
    @url  = "http://whatever.com"
    mail(:to => user.email,
         :subject => "Welcome to Whatever",
         :template_path => '**your_path**',
         )
  end
end

Take a look at 2.4 Mailer Views for more info.

2012-04-04 19:41
by Nobita
Ads