Your application is growing, and you are starting to have a complex mailing system: notification emails, retention emails, misc user emails, admin emails, etc...
It's time to clean up your mailers !
You may already have a single mailer, responsible of every emails, like this one:
app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
SENDER_EMAIL = '[email protected]'
SENDER = "elCurator <#{SENDER_EMAIL}>"
default from: SENDER
...
def new_article_notification(user, article)
@user = user
@article = article
I18n.with_locale(UserMailer.user_locale user) do
mail( to: user.email,
subject: I18n.t('user_mailer.new_article_notification.subject'))
end
end
...
def one_month_inactive_user(user)
@user = user
I18n.with_locale(UserMailer.user_locale user) do
mail to: user.email,
subject: I18n.t('user_mailer.one_month_inactive_user.subject')
end
end
...
private
def self.user_locale(user)
user.try(:locale) || ENV['DEFAULT_LOCALE'] || :fr
end
end
Associated templates should be:
- app/views/user_mailer/new_article_notification.html.haml
- app/views/user_mailer/one_month_inactive_user.html.haml
And I18n localizaion files:
- config/locales/mailers/user_mailer.en.yml
- config/locales/mailers/user_mailer.fr.yml
Let's split our single mailer to separate emails with different responsibilities. Here we'll have a NotificationMailer and a RetentionMailer.
app/mailers/notification_mailer.rb
class NotificationMailer < ActionMailer::Base
SENDER_EMAIL = '[email protected]'
SENDER = "elCurator <#{SENDER_EMAIL}>"
default from: SENDER
...
def new_article_notification(user, article)
@user = user
@article = article
I18n.with_locale(NotificationMailer.user_locale user) do
mail( to: user.email,
subject: I18n.t('notification_mailer.new_article_notification.subject'))
end
end
...
private
def self.user_locale(user)
user.try(:locale) || ENV['DEFAULT_LOCALE'] || :fr
end
end
app/mailers/retention_mailer.rb
class RetentionMailer < ActionMailer::Base
SENDER_EMAIL = '[email protected]'
SENDER = "elCurator <#{SENDER_EMAIL}>"
default from: SENDER
...
def one_month_inactive_user(user)
@user = user
I18n.with_locale(RetentionMailer.user_locale user) do
mail to: user.email,
subject: I18n.t('retention_mailer.one_month_inactive_user.subject')
end
end
...
private
def self.user_locale(user)
user.try(:locale) || ENV['DEFAULT_LOCALE'] || :fr
end
end
Templates have to be moved this way:
- app/views/notification_mailer/new_article_notification.html.haml
- app/views/retention_mailer/one_month_inactive_user.html.haml
Note that the I18n paths have change and are now separated for each mailer. Split your localization files too:
- config/locales/mailers/notification_mailer.en.yml
- config/locales/mailers/notification_mailer.fr.yml
- config/locales/mailers/retention_mailer.en.yml
- config/locales/mailers/retention_mailer.fr.yml
We have duplicated code here. Our two mailers uses the same sender. One way to clean this is to created an ApplicationMailer who will be inherited by our other mailers. Like so, NotificationMailer < ActionMailer::Base becomes NotificationMailer < ApplicationMailer.
app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
SENDER_EMAIL = '[email protected]'
SENDER = "elCurator <#{SENDER_EMAIL}>"
default from: SENDER
private
def self.user_locale(user)
user.try(:locale) || ENV['DEFAULT_LOCALE'] || :fr
end
end
app/mailers/notification_mailer.rb
class NotificationMailer < ApplicationMailer
...
def new_article_notification(user, article)
@user = user
@article = article
I18n.with_locale(NotificationMailer.user_locale user) do
mail( to: user.email,
subject: I18n.t('notification_mailer.new_article_notification.subject'))
end
end
...
end
app/mailers/retention_mailer.rb
class RetentionMailer < ApplicationMailer
...
def one_month_inactive_user(user)
@user = user
I18n.with_locale(RetentionMailer.user_locale user) do
mail to: user.email,
subject: I18n.t('retention_mailer.one_month_inactive_user.subject')
end
end
...
end
You may want to move you templates in a mailers folder now, to have something like this:
- app/views/mailers/notification_mailer/new_article_notification.html.haml
- app/views/mailers/retention_mailer/one_month_inactive_user.html.haml
Rails defaults settings wont work if you try this, because it won't search your templates within the app/views/mailers folder. One way to do this is to change the default template path in the ApplicationMailer, to find templates in app/views/mailers/{mailer_name}.
app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
SENDER_EMAIL = '[email protected]'
SENDER = "elCurator <#{SENDER_EMAIL}>"
default from: SENDER
default template_path: -> (mailer) { "mailers/#{mailer.class.name.underscore}" }
private
def self.user_locale(user)
user.try(:locale) || ENV['DEFAULT_LOCALE'] || :fr
end
end
Now that we moved our templates in another folder, make shure that your relative I18n paths are not broken. All you mailer locales have to be moved in the mailers yml property.
app/views/mailers/notification_mailer/new_article_notification.html.haml
-# This relavite I18n path will search 'mailers.notification_mailer.new_article_notification.message'
.message= i18n.t('.message')
config/locales/mailers/notification_mailer.en.yml
en:
mailers:
notification_mailer:
new_article_notification:
message: New article!