1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #6839 from bcardarella/async-actionmailer

Async actionmailer
This commit is contained in:
Aaron Patterson 2012-06-26 00:04:09 -07:00
commit ee74366da3
8 changed files with 86 additions and 0 deletions

View file

@ -2,6 +2,8 @@
* Raise an `ActionView::MissingTemplate` exception when no implicit template could be found. *Damien Mathieu*
* Asynchronously send messages via the Rails Queue *Brian Cardarella*
## Rails 3.2.5 (Jun 1, 2012) ##
* No changes.

View file

@ -0,0 +1,39 @@
require 'delegate'
module ActionMailer::Async
def method_missing(method_name, *args)
if action_methods.include?(method_name.to_s)
QueuedMessage.new(queue, self, method_name, *args)
else
super
end
end
def queue
Rails.queue
end
class QueuedMessage < ::Delegator
attr_reader :queue
def initialize(queue, mailer_class, method_name, *args)
@queue = queue
@mailer_class = mailer_class
@method_name = method_name
@args = args
end
def __getobj__
@actual_message ||= @mailer_class.send(:new, @method_name, *@args).message
end
def run
__getobj__.deliver
end
# Will push the message onto the Queue to be processed
def deliver
@queue << self
end
end
end

View file

@ -456,6 +456,18 @@ module ActionMailer #:nodoc:
super || action_methods.include?(method.to_s)
end
# Will force ActionMailer to push new messages to the queue defined
# in the ActionMailer class when set to true
#
# class WelcomeMailer < ActionMailer::Base
# self.async = true
def async=(truth)
if truth
require 'action_mailer/async'
extend ActionMailer::Async
end
end
protected
def set_payload_for_mail(payload, mail) #:nodoc:

View file

@ -7,6 +7,8 @@ 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 +421,26 @@ class BaseTest < ActiveSupport::TestCase
assert_equal(1, BaseMailer.deliveries.length)
end
def stub_queue(klass, queue)
Class.new(klass) {
extend Module.new {
define_method :queue do
queue
end
}
}
end
test "delivering message asynchronously" do
testing_queue = Rails::Queueing::TestQueue.new
AsyncMailer.delivery_method = :test
AsyncMailer.deliveries.clear
stub_queue(AsyncMailer, testing_queue).welcome.deliver
assert_equal(0, AsyncMailer.deliveries.length)
testing_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 +456,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

View file

@ -0,0 +1 @@
Welcome

View file

@ -0,0 +1,3 @@
class AsyncMailer < BaseMailer
self.async = true
end

View file

@ -39,6 +39,9 @@
* Rails::Plugin has gone. Instead of adding plugins to vendor/plugins use gems or bundler with path or git dependencies. *Santiago Pastorino*
* Set config.action_mailer.async = true to turn on asynchronous
message delivery *Brian Cardarella*
## Rails 3.2.2 (March 1, 2012) ##

View file

@ -67,5 +67,8 @@ module <%= app_const_base %>
# Version of your assets, change this if you want to expire all your assets.
config.assets.version = '1.0'
<% end -%>
# Enable app-wide asynchronous ActionMailer
# config.action_mailer.async = true
end
end