Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add a `:subject_interpolations` option to `ActionMailer::Base#mail` #9046

Merged
merged 1 commit into from

5 participants

@exviva

It allows to have a properly scoped default I18n subject, but with interpolations, which
will be populated from the :subject_interpolations hash, e.g.:

# config/locales/en.yml
en:
  user_mailer:
    welcome:
      subject: 'Hello, %{username}'

# app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
  def welcome(user)
    mail(subject_interpolations: {username: user.name})
  end
end

I was also thinking of not introducing a new option, but use the :subject option, but detect if it's a Hash, and if so, pass it as interpolations to the default i18n subject.

As usual, open for feedback.

@josevalim
Owner

Couldn't this simply be:

mail(subject: t(".subject", username: user.name))
@rafaelfranca

Yes. Agree with @josevalim. It is simpler and clearer.

@rafaelfranca rafaelfranca reopened this
@rafaelfranca

Oops! Closed by mistake.

@carlosantoniodasilva

Also important to notice that you can always override default_i18n_subject in your own mailer :)

@exviva

Actually the thing I cared about the most was to not have to implement mailer_scope on my own. Yeah, the solution with t('.subject' ... is good enough :).

@exviva exviva closed this
@exviva exviva reopened this
@exviva

Actually, t('.subject' ...) doesn't work, it'd only work in the views. So you'd still need to re-implement mailer_scope yourself :/.

@dmathieu
Collaborator

You should be able to use I18n.t.

@exviva

@dmathieu the t method does work, it's the ".subject" lazy lookup that doesn't work. It's not scoped to [mailer_scope, action_name] as I'd like it to be.

@carlosantoniodasilva

@exviva so it would make sense to extract mailer_scope to another protected method then, so you can reuse.

@exviva

@carlosantoniodasilva well, sort of. What I'd like to achieve, is being able to easily use the default subject I18n structure, but with interpolation. Even if mailer_scope were a method, I'd still need to join it with action_name and ".subject", so it's not as elegant.

I'm aware that this is a tiny improvement, so if your call is that it's not worth the costs, I'm totally fine with that.

What do you think about allowing the :subject option to be a Hash, and if it is, treat it as interpolations for the default I18n subject?

@carlosantoniodasilva

@exviva This has been discussed in #2314, the result is that it'd bring too much indirection, please see there.

So instead of adding a new option / API, we could just allow default_i18n_subject to receive the extra interpolation hash, so you can call it from your mailers:

def default_i18n_subject(interpolations = {})
  mailer_scope = self.class.mailer_name.tr('/', '.')
  I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
end

mail subject: default_i18n_subject(message: "OMGLOL")

Wdyt?

@exviva

@carlosantoniodasilva that's a very reasonable compromise, I'll implement it and ping you back. Thanks!

@exviva

@carlosantoniodasilva done, let me know what you think

actionmailer/lib/action_mailer/base.rb
@@ -726,9 +726,10 @@ def set_content_type(m, user_content_type, class_default)
# Translates the +subject+ using Rails I18n class under <tt>[mailer_scope, action_name]</tt> scope.
# If it does not find a translation for the +subject+ under the specified scope it will default to a
# humanized version of the <tt>action_name</tt>.
- def default_i18n_subject #:nodoc:
+ # If the subject has interpolations, you can pass them through the +interpolations+ parameter.
+ def default_i18n_subject(interpolations = {}) #:nodoc:

I think we can remove the nodoc now then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@carlosantoniodasilva

Other than that, seems good to me.

@exviva exviva Allow passing interpolations to `#default_i18n_subject`, e.g.:
    # config/locales/en.yml
    en:
      user_mailer:
        welcome:
          subject: 'Hello, %{username}'

    # app/mailers/user_mailer.rb
    class UserMailer < ActionMailer::Base
      def welcome(user)
        mail(subject: default_i18n_subject(username: user.name))
      end
    end
57bfbc2
@carlosantoniodasilva carlosantoniodasilva merged commit 01341e3 into rails:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 24, 2013
  1. @exviva

    Allow passing interpolations to `#default_i18n_subject`, e.g.:

    exviva authored
        # config/locales/en.yml
        en:
          user_mailer:
            welcome:
              subject: 'Hello, %{username}'
    
        # app/mailers/user_mailer.rb
        class UserMailer < ActionMailer::Base
          def welcome(user)
            mail(subject: default_i18n_subject(username: user.name))
          end
        end
This page is out of date. Refresh to see the latest.
View
19 actionmailer/CHANGELOG.md
@@ -1,6 +1,23 @@
## Rails 4.0.0 (unreleased) ##
-* Eager loading made to use relation's in_clause_length instead of host's one.
+* Allow passing interpolations to `#default_i18n_subject`, e.g.:
+
+ # config/locales/en.yml
+ en:
+ user_mailer:
+ welcome:
+ subject: 'Hello, %{username}'
+
+ # app/mailers/user_mailer.rb
+ class UserMailer < ActionMailer::Base
+ def welcome(user)
+ mail(subject: default_i18n_subject(username: user.name))
+ end
+ end
+
+ *Olek Janiszewski*
+
+* Eager loading made to use relation's `in_clause_length` instead of host's one.
Fix #8474
*Boris Staal*
View
5 actionmailer/lib/action_mailer/base.rb
@@ -726,9 +726,10 @@ def set_content_type(m, user_content_type, class_default)
# Translates the +subject+ using Rails I18n class under <tt>[mailer_scope, action_name]</tt> scope.
# If it does not find a translation for the +subject+ under the specified scope it will default to a
# humanized version of the <tt>action_name</tt>.
- def default_i18n_subject #:nodoc:
+ # If the subject has interpolations, you can pass them through the +interpolations+ parameter.
+ def default_i18n_subject(interpolations = {})
mailer_scope = self.class.mailer_name.tr('/', '.')
- I18n.t(:subject, scope: [mailer_scope, action_name], default: action_name.humanize)
+ I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
end
def collect_responses(headers) #:nodoc:
View
6 actionmailer/test/base_test.rb
@@ -209,6 +209,12 @@ def teardown
assert_equal "New Subject!", email.subject
end
+ test 'default subject can have interpolations' do
+ I18n.backend.store_translations('en', base_mailer: {with_subject_interpolations: {subject: 'Will the real %{rapper_or_impersonator} please stand up?'}})
+ email = BaseMailer.with_subject_interpolations
+ assert_equal 'Will the real Slim Shady please stand up?', email.subject
+ end
+
test "translations are scoped properly" do
I18n.backend.store_translations('en', base_mailer: {email_with_translations: {greet_user: "Hello %{name}!"}})
email = BaseMailer.email_with_translations
View
4 actionmailer/test/mailers/base_mailer.rb
@@ -123,4 +123,8 @@ def with_nil_as_return_value(hash = {})
mail(:template_name => "welcome")
nil
end
+
+ def with_subject_interpolations
+ mail(subject: default_i18n_subject(rapper_or_impersonator: 'Slim Shady'), body: '')
+ end
end
Something went wrong with that request. Please try again.