Permalink
Browse files

remove AM delegating register_observer and register_interceptor to Ma…

…il and instead implement smarter versions allowing for string class names, also added proper Railtie support with tests.

Signed-off-by: José Valim <jose.valim@gmail.com>
  • Loading branch information...
1 parent 454ec93 commit 284ca810c17a89d15d809ba203289487044fcff9 @joshk joshk committed with josevalim Apr 2, 2011
@@ -4,6 +4,7 @@
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/proc'
+require 'active_support/core_ext/string/inflections'
require 'action_mailer/log_subscriber'
module ActionMailer #:nodoc:
@@ -349,9 +350,6 @@ class Base < AbstractController::Base
helper ActionMailer::MailHelper
include ActionMailer::OldApi
- delegate :register_observer, :to => Mail
- delegate :register_interceptor, :to => Mail
-
private_class_method :new #:nodoc:
class_attribute :default_params
@@ -363,6 +361,32 @@ class Base < AbstractController::Base
}.freeze
class << self
+ # Register one or more Observers which will be notified when mail is delivered.
+ def register_observers(*observers)
+ observers.flatten.compact.each { |observer| register_observer(observer) }
+ end
+
+ # Register one or more Interceptors which will be called before mail is sent.
+ def register_interceptors(*interceptors)
+ interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
+ end
+
+ # Register an Observer which will be notified when mail is delivered.
+ # Either a class or a string can be passed in as the Observer. If a string is passed in
+ # it will be <tt>constantize</tt>d.
+ def register_observer(observer)
+ delivery_observer = (observer.respond_to?(:delivered_email) ? observer : observer.constantize)
+ Mail.register_observer(delivery_observer)
+ end
+
+ # Register an Inteceptor which will be called before mail is sent.
+ # Either a class or a string can be passed in as the Observer. If a string is passed in
@arthurschreiber

arthurschreiber Apr 4, 2011

The docs here describe behaviour that is pretty different from what is implemented in the code.
The passed value gets constantized if it does not respond to #delivering_email, which actually is a bit weird.

@josevalim

josevalim Apr 4, 2011

Contributor

Right, it should explicitly check for a string here if we are calling constantize.

+ # it will be <tt>constantize</tt>d.
+ def register_interceptor(interceptor)
+ delivery_interceptor = (interceptor.respond_to?(:delivering_email) ? interceptor : interceptor.constantize)
+ Mail.register_interceptor(delivery_interceptor)
+ end
+
def mailer_name
@mailer_name ||= name.underscore
end
@@ -19,13 +19,17 @@ class Railtie < Rails::Railtie
options.stylesheets_dir ||= paths["public/stylesheets"].first
# make sure readers methods get compiled
- options.asset_path ||= app.config.asset_path
- options.asset_host ||= app.config.asset_host
+ options.asset_path ||= app.config.asset_path
+ options.asset_host ||= app.config.asset_host
ActiveSupport.on_load(:action_mailer) do
include AbstractController::UrlFor
extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
include app.routes.mounted_helpers
+
+ register_interceptors(options.delete(:interceptors))
+ register_observers(options.delete(:observers))
+
options.each { |k,v| send("#{k}=", v) }
end
end
@@ -478,25 +478,65 @@ def self.delivered_email(mail)
end
end
+ class MySecondObserver
+ def self.delivered_email(mail)
+ end
+ end
+
test "you can register an observer to the mail object that gets informed on email delivery" do
ActionMailer::Base.register_observer(MyObserver)
mail = BaseMailer.welcome
MyObserver.expects(:delivered_email).with(mail)
mail.deliver
end
+ test "you can register an observer using its stringified name to the mail object that gets informed on email delivery" do
+ ActionMailer::Base.register_observer("BaseTest::MyObserver")
+ mail = BaseMailer.welcome
+ MyObserver.expects(:delivered_email).with(mail)
+ mail.deliver
+ end
+
+ test "you can register multiple observers to the mail object that both get informed on email delivery" do
+ ActionMailer::Base.register_observers("BaseTest::MyObserver", MySecondObserver)
+ mail = BaseMailer.welcome
+ MyObserver.expects(:delivered_email).with(mail)
+ MySecondObserver.expects(:delivered_email).with(mail)
+ mail.deliver
+ end
+
class MyInterceptor
def self.delivering_email(mail)
end
end
+ class MySecondInterceptor
+ def self.delivering_email(mail)
+ end
+ end
+
test "you can register an interceptor to the mail object that gets passed the mail object before delivery" do
ActionMailer::Base.register_interceptor(MyInterceptor)
mail = BaseMailer.welcome
MyInterceptor.expects(:delivering_email).with(mail)
mail.deliver
end
+ test "you can register an interceptor using its stringified name to the mail object that gets passed the mail object before delivery" do
+ ActionMailer::Base.register_interceptor("BaseTest::MyInterceptor")
+ mail = BaseMailer.welcome
+ MyInterceptor.expects(:delivering_email).with(mail)
+ mail.deliver
+ end
+
+ test "you can register multiple interceptors to the mail object that both get passed the mail object before delivery" do
+ ActionMailer::Base.register_interceptors("BaseTest::MyInterceptor", MySecondInterceptor)
+ mail = BaseMailer.welcome
+ MyInterceptor.expects(:delivering_email).with(mail)
+ MySecondInterceptor.expects(:delivering_email).with(mail)
+ mail.deliver
+ end
+
test "being able to put proc's into the defaults hash and they get evaluated on mail sending" do
mail1 = ProcMailer.welcome
yesterday = 1.day.ago
@@ -1,5 +1,18 @@
require "isolation/abstract_unit"
+class ::MyMailInterceptor
+ def self.delivering_email(email); email; end
+end
+
+class ::MyOtherMailInterceptor < ::MyMailInterceptor; end
+
+class ::MyMailObserver
+ def self.delivered_email(email); email; end
+end
+
+class ::MyOtherMailObserver < ::MyMailObserver; end
+
+
module ApplicationTests
class ConfigurationTest < Test::Unit::TestCase
include ActiveSupport::Testing::Isolation
@@ -245,6 +258,58 @@ def index
assert_equal res, last_response.body # value should be unchanged
end
+ test "registers interceptors with ActionMailer" do
+ add_to_config <<-RUBY
+ config.action_mailer.interceptors = MyMailInterceptor
+ RUBY
+
+ require "#{app_path}/config/environment"
+ require "mail"
+
+ ActionMailer::Base
+
+ assert_equal [::MyMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors")
+ end
+
+ test "registers multiple interceptors with ActionMailer" do
+ add_to_config <<-RUBY
+ config.action_mailer.interceptors = [MyMailInterceptor, "MyOtherMailInterceptor"]
+ RUBY
+
+ require "#{app_path}/config/environment"
+ require "mail"
+
+ ActionMailer::Base
+
+ assert_equal [::MyMailInterceptor, ::MyOtherMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors")
+ end
+
+ test "registers observers with ActionMailer" do
+ add_to_config <<-RUBY
+ config.action_mailer.observers = MyMailObserver
+ RUBY
+
+ require "#{app_path}/config/environment"
+ require "mail"
+
+ ActionMailer::Base
+
+ assert_equal [::MyMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers")
+ end
+
+ test "registers multiple observers with ActionMailer" do
+ add_to_config <<-RUBY
+ config.action_mailer.observers = [MyMailObserver, "MyOtherMailObserver"]
+ RUBY
+
+ require "#{app_path}/config/environment"
+ require "mail"
+
+ ActionMailer::Base
+
+ assert_equal [::MyMailObserver, ::MyOtherMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers")
+ end
+
test "config.action_controller.perform_caching = false" do
make_basic_app do |app|
app.config.action_controller.perform_caching = false

0 comments on commit 284ca81

Please sign in to comment.