aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/lib/action_mailer/async.rb41
-rw-r--r--actionmailer/lib/action_mailer/base.rb7
-rw-r--r--actionmailer/test/base_test.rb14
-rw-r--r--actionmailer/test/fixtures/async_mailer/welcome.erb1
-rw-r--r--actionmailer/test/mailers/async_mailer.rb3
5 files changed, 66 insertions, 0 deletions
diff --git a/actionmailer/lib/action_mailer/async.rb b/actionmailer/lib/action_mailer/async.rb
new file mode 100644
index 0000000000..6f768ac286
--- /dev/null
+++ b/actionmailer/lib/action_mailer/async.rb
@@ -0,0 +1,41 @@
+module ActionMailer::Async
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def method_missing(method_name, *args)
+ if action_methods.include?(method_name.to_s)
+ QueuedMessage.new(self, method_name, *args)
+ else
+ super
+ end
+ end
+ end
+
+ class QueuedMessage
+ delegate :to_s, :to => :actual_message
+
+ def initialize(mailer_class, method_name, *args)
+ @mailer_class = mailer_class
+ @method_name = method_name
+ *@args = *args
+ end
+
+ def run
+ actual_message.deliver
+ end
+
+ def deliver
+ Rails.queue << self
+ end
+
+ def actual_message
+ @actual_message ||= @mailer_class.send(:new, @method_name, *@args).message
+ end
+
+ def method_missing(method_name, *args)
+ actual_message.send(method_name, *args)
+ end
+ end
+end
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 739f9a52a9..f40b85549e 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -456,6 +456,13 @@ module ActionMailer #:nodoc:
super || action_methods.include?(method.to_s)
end
+ def async=(truth)
+ if truth
+ require 'action_mailer/async'
+ include ActionMailer::Async
+ end
+ end
+
protected
def set_payload_for_mail(payload, mail) #:nodoc:
diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb
index 1b2e39b3f7..fdc784029b 100644
--- a/actionmailer/test/base_test.rb
+++ b/actionmailer/test/base_test.rb
@@ -7,6 +7,9 @@ require 'active_support/time'
require 'mailers/base_mailer'
require 'mailers/proc_mailer'
require 'mailers/asset_mailer'
+require 'mailers/async_mailer'
+
+require 'rails/queueing'
class BaseTest < ActiveSupport::TestCase
def teardown
@@ -419,6 +422,16 @@ class BaseTest < ActiveSupport::TestCase
assert_equal(1, BaseMailer.deliveries.length)
end
+ test "delivering message asynchronously" do
+ Rails.stubs(:queue).returns(Rails::Queueing::TestQueue.new)
+ AsyncMailer.delivery_method = :test
+ AsyncMailer.deliveries.clear
+ AsyncMailer.welcome.deliver
+ assert_equal(0, AsyncMailer.deliveries.length)
+ Rails.queue.drain
+ assert_equal(1, AsyncMailer.deliveries.length)
+ end
+
test "calling deliver, ActionMailer should yield back to mail to let it call :do_delivery on itself" do
mail = Mail::Message.new
mail.expects(:do_delivery).once
@@ -434,6 +447,7 @@ class BaseTest < ActiveSupport::TestCase
end
test "should raise if missing template in implicit render" do
+ BaseMailer.deliveries.clear
assert_raises ActionView::MissingTemplate do
BaseMailer.implicit_different_template('missing_template').deliver
end
diff --git a/actionmailer/test/fixtures/async_mailer/welcome.erb b/actionmailer/test/fixtures/async_mailer/welcome.erb
new file mode 100644
index 0000000000..01f3f00c63
--- /dev/null
+++ b/actionmailer/test/fixtures/async_mailer/welcome.erb
@@ -0,0 +1 @@
+Welcome \ No newline at end of file
diff --git a/actionmailer/test/mailers/async_mailer.rb b/actionmailer/test/mailers/async_mailer.rb
new file mode 100644
index 0000000000..ce601e7343
--- /dev/null
+++ b/actionmailer/test/mailers/async_mailer.rb
@@ -0,0 +1,3 @@
+class AsyncMailer < BaseMailer
+ self.async = true
+end