Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Do not render views when mail() isn't called. (NullMail refactoring) #8048

Merged
merged 1 commit into from

3 participants

@senny
Owner

I introduced a NullMail class. When mail() is never called an instance of NullMail is returned in place of a regular Mail.

This refactoring fixes #7761

@senny
Owner

I created a very small class called NullMail. What is the best practice in the rails codebase for tiny classes. Do you embed those in side the class that uses them or do you put them in a new file?

Also my BlankSlate implementation is very basic. Do you use a different pattern in the rails source?

@KieranP @jeremy @rafaelfranca What do you think?

actionmailer/lib/action_mailer/null_mail.rb
@@ -0,0 +1,7 @@
+class NullMail
@frodsan
frodsan added a note

Could you please add a # :nodoc: directive here?

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

@frodsan done.

actionmailer/lib/action_mailer/base.rb
@@ -504,13 +505,17 @@ def method_missing(method_name, *args)
# method, for instance).
def initialize(method_name=nil, *args)
super()
- @_message = Mail.new
@rafaelfranca Owner

Could we leave this initialization here? Without it we can receive a "non-initialized instance variable" warning

@senny Owner
senny added a note

yes I'll move it there. I put it in process because I think it communicates the intent better, than overwriting the variable later. If it produces warnings though I'll put it back.

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

I would put NullMail inside of ActionMailer::Base

@senny
Owner

@rafaelfranca moved NullMail. Can you check again?

@rafaelfranca

Seems good to me. Thank you

@rafaelfranca rafaelfranca merged commit a273b6b into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
5 actionmailer/CHANGELOG.md
@@ -1,5 +1,10 @@
## Rails 4.0.0 (unreleased) ##
+* Do not render views when mail() isn't called.
+ Fix #7761
+
+ *Yves Senn*
+
* Support `Mailer.deliver_foo(*args)` as a synonym for
`Mailer.foo(*args).deliver`. This makes it easy to write e.g.
`Mailer.expects(:deliver_foo)` when testing code that calls
View
14 actionmailer/lib/action_mailer/base.rb
@@ -510,7 +510,19 @@ def initialize(method_name=nil, *args)
def process(*args) #:nodoc:
lookup_context.skip_default_locale!
- super
+
+ generated_mail = super
+ unless generated_mail
+ @_message = NullMail.new
+ end
+ end
+
+ class NullMail #:nodoc:
+ def body; '' end
+
+ def method_missing(*args)
+ nil
+ end
end
def mailer_name
View
6 actionmailer/test/base_test.rb
@@ -499,6 +499,12 @@ def teardown
end
end
+ test 'the view is not rendered when mail was never called' do
+ mail = BaseMailer.without_mail_call
+ assert_equal('', mail.body.to_s.strip)
+ mail.deliver
+ end
+
# Before and After hooks
class MyObserver
View
1  actionmailer/test/fixtures/base_mailer/without_mail_call.erb
@@ -0,0 +1 @@
+<% raise 'the template should not be rendered' %>
View
3  actionmailer/test/mailers/base_mailer.rb
@@ -115,4 +115,7 @@ def different_layout(layout_name='')
def email_with_translations
mail body: render("email_with_translations", formats: [:html])
end
+
+ def without_mail_call
+ end
end
Something went wrong with that request. Please try again.