Permalink
Browse files

Add deliver_at and deliver_in methods for scheduling mail

  • Loading branch information...
1 parent e4477c9 commit fdc51dd54c86f3e315f410e864b8b831281f9427 @hmarr hmarr committed with May 10, 2012
Showing with 94 additions and 0 deletions.
  1. +13 −0 README.md
  2. +20 −0 lib/resque_mailer.rb
  3. +61 −0 spec/resque_mailer_spec.rb
View
@@ -45,6 +45,19 @@ name when starting your workers.
QUEUE=application_specific_mailer rake environment resque:work
+### Using with Resque Scheduler
+
+If [resque-scheduler](https://github.com/bvandenbos/resque-scheduler) is
+installed, two extra methods will be available: `deliver_at` and `deliver_in`.
+These will enqueue mail for delivery at a specified time in the future.
+
+ # Delivers on the 25th of December, 2012
+ MyMailer.reminder_email(params).deliver_at(Time.parse('2012-12-25'))
+
+ # Delivers in 7 days
+ MyMailer.reminder_email(params).deliver_in(7.days)
+
+
## Resque::Mailer as a Project Default
If you have a variety of mailers in your application and want all of them to use
View
@@ -100,6 +100,26 @@ def deliver
end
end
+ def deliver_at(time)
+ unless resque.respond_to? :enqueue_at
+ raise "You need to install resque-scheduler to use deliver_at"
+ end
+
+ if @mailer_class.deliver?
+ resque.enqueue_at(time, @mailer_class, @method_name, *@args)
+ end
+ end
+
+ def deliver_in(time)
+ unless resque.respond_to? :enqueue_in
+ raise "You need to install resque-scheduler to use deliver_in"
+ end
+
+ if @mailer_class.deliver?
+ resque.enqueue_in(time, @mailer_class, @method_name, *@args)
+ end
+ end
+
def deliver!
actual_message.deliver!
end
View
@@ -4,6 +4,11 @@ class FakeResque
def self.enqueue(*args); end
end
+class FakeResqueWithScheduler < FakeResque
+ def self.enqueue_in(time, *args); end
+ def self.enqueue_at(time, *args); end
+end
+
class Rails3Mailer < ActionMailer::Base
include Resque::Mailer
default :from => "from@example.org", :subject => "Subject"
@@ -80,6 +85,62 @@ class PriorityMailer < Rails3Mailer
end
end
+ describe '#deliver_at' do
+ before(:all) do
+ @time = Time.now
+ @delivery = lambda {
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).deliver_at(@time)
+ }
+ end
+
+ context "without resque-scheduler installed" do
+ it "raises an error" do
+ lambda { @delivery.call }.should raise_exception
+ end
+ end
+
+ context "with resque-scheduler installed" do
+ let(:resque) { FakeResqueWithScheduler }
+
+ it 'should not deliver the email synchronously' do
+ lambda { @delivery.call }.should_not change(ActionMailer::Base.deliveries, :size)
+ end
+
+ it 'should place the deliver action on the Resque "mailer" queue' do
+ resque.should_receive(:enqueue_at).with(@time, Rails3Mailer, :test_mail, Rails3Mailer::MAIL_PARAMS)
+ @delivery.call
+ end
+ end
+ end
+
+ describe '#deliver_in' do
+ before(:all) do
+ @time = 1234567
+ @delivery = lambda {
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).deliver_in(@time)
+ }
+ end
+
+ context "without resque-scheduler installed" do
+ it "raises an error" do
+ lambda { @delivery.call }.should raise_exception
+ end
+ end
+
+ context "with resque-scheduler installed" do
+ let(:resque) { FakeResqueWithScheduler }
+
+ it 'should not deliver the email synchronously' do
+ lambda { @delivery.call }.should_not change(ActionMailer::Base.deliveries, :size)
+ end
+
+ it 'should place the deliver action on the Resque "mailer" queue' do
+ resque.should_receive(:enqueue_in).with(@time, Rails3Mailer, :test_mail, Rails3Mailer::MAIL_PARAMS)
+ @delivery.call
+ end
+ end
+ end
+
describe '#deliver!' do
it 'should deliver the email synchronously' do
lambda { Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).deliver! }.should change(ActionMailer::Base.deliveries, :size).by(1)

0 comments on commit fdc51dd

Please sign in to comment.