Added ActionMailer::DeliverLater

This commit is contained in:
Abdelkader Boudih 2014-08-12 18:24:19 +00:00
parent 22ee993825
commit 67f8b6b2bc
11 changed files with 163 additions and 10 deletions

View File

@ -45,4 +45,5 @@ module ActionMailer
autoload :Previews, 'action_mailer/preview'
autoload :TestCase
autoload :TestHelper
autoload :DeliverLater
end

View File

@ -549,7 +549,11 @@ module ActionMailer
def method_missing(method_name, *args) # :nodoc:
if respond_to?(method_name)
new(method_name, *args).message
if defined?(::ActiveJob) && action_methods.include?(method_name.to_s)
DeliverLater::MailMessageWrapper.new(self, method_name, *args)
else
new(method_name, *args).message
end
else
super
end

View File

@ -0,0 +1,9 @@
require 'active_job'
module ActionMailer
module DeliverLater
extend ActiveSupport::Autoload
autoload :Job
autoload :MailMessageWrapper
end
end

View File

@ -0,0 +1,11 @@
module ActionMailer
module DeliverLater
class Job < ActiveJob::Base
queue_as :mailers
def perform(mailer, mail_method, delivery_method, *args)
mailer.constantize.send(mail_method, *args).send(delivery_method)
end
end
end
end

View File

@ -0,0 +1,46 @@
module ActionMailer
module DeliverLater
class MailMessageWrapper < Delegator
def initialize(mailer, mail_method, *args)
@mailer = mailer
@mail_method = mail_method
@args = args
__getobj__
end
def __getobj__
@obj ||= @mailer.send(:new, @mail_method, *@args).message
end
def __setobj__(obj)
@obj = obj
end
def deliver_later!(options={})
enqueue_delivery :deliver!, options
end
def deliver_later(options={})
enqueue_delivery :deliver, options
end
def method_missing(m, *args, &block)
__getobj__.__send__(m, *args, &block)
end
private
def enqueue_delivery(delivery_method, options={})
args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args
enqueue_method = :enqueue
if options[:at]
enqueue_method = :enqueue_at
args.unshift options[:at]
elsif options[:in]
enqueue_method = :enqueue_in
args.unshift options[:in]
end
ActionMailer::DeliverLater::Job.send enqueue_method, *args
end
end
end
end

View File

@ -0,0 +1,82 @@
# encoding: utf-8
gem 'activejob'
require 'action_mailer/deliver_later'
require 'abstract_unit'
require 'minitest/mock'
require_relative 'mailers/delayed_mailer'
class MailerTest < ActiveSupport::TestCase
setup do
@previous_logger = ActiveJob::Base.logger
@previous_delivery_method = ActionMailer::Base.delivery_method
ActionMailer::Base.delivery_method = :test
ActiveJob::Base.logger = Logger.new('/dev/null')
@mail = DelayedMailer.test_message(1, 2, 3)
ActionMailer::Base.deliveries.clear
end
teardown do
ActiveJob::Base.logger = @previous_logger
ActionMailer::Base.delivery_method = @previous_delivery_method
end
test 'should be a MailMessageWrapper' do
assert_equal @mail.class, ActionMailer::DeliverLater::MailMessageWrapper
end
test 'its object should be a Mail::Message' do
assert_equal @mail.__getobj__.class, Mail::Message
end
test 'should respond to .deliver' do
assert_respond_to @mail, :deliver
end
test 'should respond to .deliver!' do
assert_respond_to @mail, :deliver!
end
test 'should respond to .deliver_later' do
assert_respond_to @mail, :deliver_later
end
test 'should respond to .deliver_later!' do
assert_respond_to @mail, :deliver_later!
end
test 'should enqueue and run correctly in activejob' do
@mail.deliver_later!
assert_equal ActionMailer::Base.deliveries.size, 1
end
test 'should enqueue the email with :deliver delivery method' do
ret = ActionMailer::DeliverLater::Job.stub :enqueue, ->(*args){ args } do
@mail.deliver_later
end
assert_equal ret, ["DelayedMailer", "test_message", "deliver", 1, 2, 3]
end
test 'should enqueue the email with :deliver! delivery method' do
ret = ActionMailer::DeliverLater::Job.stub :enqueue, ->(*args){ args } do
@mail.deliver_later!
end
assert_equal ret, ["DelayedMailer", "test_message", "deliver!", 1, 2, 3]
end
test 'should enqueue a delivery with a delay' do
ret = ActionMailer::DeliverLater::Job.stub :enqueue_in, ->(*args){ args } do
@mail.deliver_later in: 600
end
assert_equal ret, [600, "DelayedMailer", "test_message", "deliver", 1, 2, 3]
end
test 'should enqueue a delivery at a specific time' do
later_time = Time.now.to_i + 3600
ret = ActionMailer::DeliverLater::Job.stub :enqueue_at, ->(*args){ args } do
@mail.deliver_later at: later_time
end
assert_equal ret, [later_time, "DelayedMailer", "test_message", "deliver", 1, 2, 3]
end
end

View File

@ -0,0 +1,6 @@
class DelayedMailer < ActionMailer::Base
def test_message(*)
mail(from: 'test-sender@test.com', to: 'test-receiver@test.com', subject: 'Test Subject', body: 'Test Body')
end
end

View File

@ -23,8 +23,6 @@
require 'active_support'
require 'active_support/rails'
require 'active_job/railtie' if defined?(Rails)
require 'active_job/version'
module ActiveJob

View File

@ -7,7 +7,7 @@ module ActiveJob
included do
cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
around_enqueue do |job, block, _|
around_enqueue do |_, block, _|
tag_logger do
block.call
end
@ -17,7 +17,7 @@ module ActiveJob
tag_logger(job.class.name, job.job_id) do
payload = {adapter: job.class.queue_adapter, job: job.class, args: job.arguments}
ActiveSupport::Notifications.instrument("perform_start.active_job", payload.dup)
ActiveSupport::Notifications.instrument("perform.active_job", payload) do |payload|
ActiveSupport::Notifications.instrument("perform.active_job", payload) do
block.call
end
end

View File

@ -1 +0,0 @@
require 'active_job'

View File

@ -1,7 +1,4 @@
require 'bundler'
Bundler.setup
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
require File.expand_path('../../../load_paths', __FILE__)
require 'active_job'