Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add ability to define callbacks in ActionMailer using AbstractControl…

…ler::Callbacks.

Prior to this commit, there isn't a good way of adding things like
default inline attachments to an email.  This Stack Overflow thread
shows people using hooks like the 'default' method in ActionMailer::Base
to call a Proc for message configuration:

http://stackoverflow.com/questions/5113121/rails-use-same-attachment-for-all-emails-using-layout

This has the unintended side effect of setting a message header, so it's not a good solution.

This pull request adds support for message modifications by including AbstractController:Callbacks
in ActionMailer::Base. It includes tests and documentation for the functionality
provided by including this module.
  • Loading branch information...
commit 4f28c4fc9a51bbab76d5dcde033c47aa6711339b 1 parent 4d2d0d9
@jsl jsl authored
View
28 actionmailer/lib/action_mailer/base.rb
@@ -267,6 +267,33 @@ module ActionMailer #:nodoc:
# set something in the defaults using a proc, and then set the same thing inside of your
# mailer method, it will get over written by the mailer method.
#
+ # = Callbacks
+ #
+ # You can specify callbacks using before_filter and after_filter for configuring your messages.
+ # This may be useful, for example, when you want to add default inline attachments for all
+ # messages sent out by a certain mailer class:
+ #
+ # class Notifier < ActionMailer::Base
+ # before_filter :add_inline_attachment!
+ #
+ # def welcome
+ # mail
+ # end
+ #
+ # private
+ #
+ # def add_inline_attachment!
+ # attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
+ # end
+ # end
+ #
+ # Callbacks in ActionMailer are implemented using AbstractController::Callbacks, so you
+ # can define and configure callbacks in the same manner that you would use callbacks in
+ # classes that inherit from ActionController::Base.
+ #
+ # Note that unless you have a specific reason to do so, you should prefer using before_filter
+ # rather than after_filter in your ActionMailer classes so that headers are parsed properly.
+ #
# = Configuration options
#
# These options are specified on the class level, like
@@ -330,6 +357,7 @@ class Base < AbstractController::Base
include AbstractController::Helpers
include AbstractController::Translation
include AbstractController::AssetPaths
+ include AbstractController::Callbacks
self.protected_instance_variables = [:@_action_has_layout]
View
46 actionmailer/test/base_test.rb
@@ -552,6 +552,52 @@ def self.delivering_email(mail)
assert_equal("Thanks for signing up this afternoon", mail.subject)
end
+ test "modifying the mail message with a before_filter" do
+ class BeforeFilterMailer < ActionMailer::Base
+ before_filter :add_special_header!
+
+ def welcome ; mail ; end
+
+ private
+ def add_special_header!
+ headers('X-Special-Header' => 'Wow, so special')
+ end
+ end
+
+ assert_equal('Wow, so special', BeforeFilterMailer.welcome['X-Special-Header'].to_s)
+ end
+
+ test "modifying the mail message with an after_filter" do
+ class AfterFilterMailer < ActionMailer::Base
+ after_filter :add_special_header!
+
+ def welcome ; mail ; end
+
+ private
+ def add_special_header!
+ headers('X-Special-Header' => 'Testing')
+ end
+ end
+
+ assert_equal('Testing', AfterFilterMailer.welcome['X-Special-Header'].to_s)
+ end
+
+ test "adding an inline attachment using a before_filter" do
+ class DefaultInlineAttachmentMailer < ActionMailer::Base
+ before_filter :add_inline_attachment!
+
+ def welcome ; mail ; end
+
+ private
+ def add_inline_attachment!
+ attachments.inline["footer.jpg"] = 'hey there'
+ end
+ end
+
+ mail = DefaultInlineAttachmentMailer.welcome
+ assert_equal('image/jpeg; filename=footer.jpg', mail.attachments.inline.first['Content-Type'].to_s)
+ end
+
test "action methods should be refreshed after defining new method" do
class FooMailer < ActionMailer::Base
# this triggers action_methods
Please sign in to comment.
Something went wrong with that request. Please try again.