Skip to content

Commit

Permalink
Added cleaner API for delaying mailers in Rails 3
Browse files Browse the repository at this point in the history
Example:
	UserMailer.delay.signup(@user)

This will enqueue a job that creates the email and calls #deliver on it.
  • Loading branch information
bkeepers committed Sep 6, 2010
1 parent 129a5d5 commit 33be987
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
7 changes: 4 additions & 3 deletions lib/delayed/message_sending.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@

module Delayed
class DelayProxy < ActiveSupport::BasicObject
def initialize(target, options)
def initialize(payload_class, target, options)
@payload_class = payload_class
@target = target
@options = options
end

def method_missing(method, *args)
Job.create({
:payload_object => PerformableMethod.new(@target, method.to_sym, args),
:payload_object => @payload_class.new(@target, method.to_sym, args),
:priority => ::Delayed::Worker.default_priority
}.merge(@options))
end
end

module MessageSending
def delay(options = {})
DelayProxy.new(self, options)
DelayProxy.new(PerformableMethod, self, options)
end
alias __delay__ delay

Expand Down
21 changes: 21 additions & 0 deletions lib/delayed/performable_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'action_mailer'

module Delayed
class PerformableMailer < PerformableMethod
def perform
object.send(method, *args).deliver
end
end
end

ActionMailer::Base.class_eval do
def self.delay(options = {})
Delayed::DelayProxy.new(Delayed::PerformableMailer, self, options)
end
end

Mail::Message.class_eval do
def delay(*args)
raise RuntimeError, "Use MyMailer.delay.mailer_action(args) to delay sending of emails."
end
end
1 change: 1 addition & 0 deletions lib/delayed_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require File.dirname(__FILE__) + '/delayed/message_sending'
require File.dirname(__FILE__) + '/delayed/performable_method'
require File.dirname(__FILE__) + '/delayed/performable_mailer'
require File.dirname(__FILE__) + '/delayed/yaml_ext'
require File.dirname(__FILE__) + '/delayed/backend/base'
require File.dirname(__FILE__) + '/delayed/worker'
Expand Down
46 changes: 46 additions & 0 deletions spec/performable_mailer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'spec_helper'

require 'action_mailer'
class MyMailer < ActionMailer::Base
def signup(email)
mail :to => email, :subject => "Delaying Emails"
end
end

describe ActionMailer::Base do
describe "delay" do
it "should enqueue a PerformableEmail job" do
lambda {
job = MyMailer.delay.signup('john@example.com')
job.payload_object.class.should == Delayed::PerformableMailer
job.payload_object.method.should == :signup
job.payload_object.args.should == ['john@example.com']
}.should change { Delayed::Job.count }.by(1)
end
end

describe "delay on a mail object" do
it "should raise an exception" do
lambda {
MyMailer.signup('john@example.com').delay
}.should raise_error(RuntimeError)
end
end

describe Delayed::PerformableMailer do
describe "perform" do
before do
@email = mock('email', :deliver => true)
@mailer_class = mock('MailerClass', :signup => @email)
@mailer = Delayed::PerformableMailer.new(@mailer_class, :signup, ['john@example.com'])
end

it "should call the method and #deliver on the mailer" do
@mailer_class.should_receive(:signup).with('john@example.com')
@email.should_receive(:deliver)
@mailer.perform
end
end
end

end

0 comments on commit 33be987

Please sign in to comment.