qu_mailer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,74 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ qu_mailer (0.1.0)
5
+ actionmailer (>= 3.0.0)
6
+ qu (>= 0.1.3)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionmailer (3.1.1)
12
+ actionpack (= 3.1.1)
13
+ mail (~> 2.3.0)
14
+ actionpack (3.1.1)
15
+ activemodel (= 3.1.1)
16
+ activesupport (= 3.1.1)
17
+ builder (~> 3.0.0)
18
+ erubis (~> 2.7.0)
19
+ i18n (~> 0.6)
20
+ rack (~> 1.3.2)
21
+ rack-cache (~> 1.1)
22
+ rack-mount (~> 0.8.2)
23
+ rack-test (~> 0.6.1)
24
+ sprockets (~> 2.0.2)
25
+ activemodel (3.1.1)
26
+ activesupport (= 3.1.1)
27
+ builder (~> 3.0.0)
28
+ i18n (~> 0.6)
29
+ activesupport (3.1.1)
30
+ multi_json (~> 1.0)
31
+ builder (3.0.0)
32
+ diff-lcs (1.1.3)
33
+ erubis (2.7.0)
34
+ hike (1.2.1)
35
+ i18n (0.6.0)
36
+ mail (2.3.0)
37
+ i18n (>= 0.4.0)
38
+ mime-types (~> 1.16)
39
+ treetop (~> 1.4.8)
40
+ mime-types (1.17.2)
41
+ multi_json (1.0.3)
42
+ polyglot (0.3.3)
43
+ qu (0.1.3)
44
+ multi_json
45
+ rack (1.3.5)
46
+ rack-cache (1.1)
47
+ rack (>= 0.4)
48
+ rack-mount (0.8.3)
49
+ rack (>= 1.0.0)
50
+ rack-test (0.6.1)
51
+ rack (>= 1.0)
52
+ rspec (2.7.0)
53
+ rspec-core (~> 2.7.0)
54
+ rspec-expectations (~> 2.7.0)
55
+ rspec-mocks (~> 2.7.0)
56
+ rspec-core (2.7.1)
57
+ rspec-expectations (2.7.0)
58
+ diff-lcs (~> 1.1.2)
59
+ rspec-mocks (2.7.0)
60
+ sprockets (2.0.3)
61
+ hike (~> 1.2)
62
+ rack (~> 1.0)
63
+ tilt (~> 1.1, != 1.3.0)
64
+ tilt (1.3.3)
65
+ treetop (1.4.10)
66
+ polyglot
67
+ polyglot (>= 0.3.1)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ qu_mailer!
74
+ rspec (>= 2.6.0)
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # QuMailer
2
+
3
+ QuMailer is a library for the asynchronous delivery of emails sent out by ActionMailer in Rails 3 applications. It is heavily inspired by ResqueMailer.
4
+
5
+ Email jobs created by QuMailer are processed by [Qu](https://github.com/bkeepers/qu), a Ruby library for queuing and processing background jobs.
6
+
7
+ ## Installation
8
+
9
+ It is assumed that you are using Qu. If you aren’t already using it, please visit the [Qu project page](https://github.com/bkeepers/qu) for details on getting set up.
10
+
11
+ ### Rails 3
12
+
13
+ Add the QuMailer gem to your `Gemfile`.
14
+
15
+ ``` ruby
16
+ gem 'qu_mailer'
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Include QuMailer in your ActionMailer subclass(es):
22
+
23
+ ``` ruby
24
+ class MyMailer < ActionMailer::Base
25
+ include Qu::Mailer
26
+ end
27
+ ```
28
+
29
+ Fire up Qu with a 'mailer' queue:
30
+
31
+ ``` sh
32
+ $ bundle exec rake qu:work QUEUES=mailer,default
33
+ ```
34
+
35
+ Now, when you send a `deliver` message to an action in `MyMailer`, it will be placed on Qu’s *mailer* queue, and a Qu worker will deliver it in due course. If you want to bybass Qu in a particular scenario and send the email synchronously, then use `deliver!`.
36
+
37
+ It is recommended that instead of passing objects to your emails as parameters, record identifiers are used instead. Jobs are handled in a separate process.
38
+
39
+ ## Configuration
40
+
41
+ ### Queue Name
42
+
43
+ QuMailer defaults to a queue called `mailer`. You can change the name of the queue using an initializer.
44
+
45
+ `config/initializers/qu_mailer.rb`:
46
+
47
+ ``` ruby
48
+ Qu::Mailer.default_queue_name = 'asynchronous_electronic_mailbox'
49
+ ```
50
+
51
+ ### Excluded Environments
52
+
53
+ You may want to prevent QuMailer from sending out email in certain environments. By default QuMailer exludes the test environment. You may add additional excluded environments using an initializer.
54
+
55
+ `config/initializers/qu_mailer.rb`:
56
+
57
+ ``` ruby
58
+ Qu::Mailer.excluded_environments << :cucumber
59
+ ```
60
+
61
+ ## License
62
+
63
+ Copyright (c) 2011 Philip Poots
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining
66
+ a copy of this software and associated documentation files (the
67
+ "Software"), to deal in the Software without restriction, including
68
+ without limitation the rights to use, copy, modify, merge, publish,
69
+ distribute, sublicense, and/or sell copies of the Software, and to
70
+ permit persons to whom the Software is furnished to do so, subject to
71
+ the following conditions:
72
+
73
+ The above copyright notice and this permission notice shall be
74
+ included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
77
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
78
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
79
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
80
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
81
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
82
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "lib", "qu_mailer")
data/lib/qu_mailer.rb ADDED
@@ -0,0 +1,84 @@
1
+ module Qu
2
+ module Mailer
3
+ class << self
4
+ attr_accessor :default_queue_target, :default_queue_name
5
+ attr_reader :excluded_environments
6
+
7
+ def excluded_environments=(envs)
8
+ @excluded_environments = [*envs].map(&:to_sym)
9
+ end
10
+
11
+ def included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+ end
15
+
16
+ self.default_queue_target = ::Qu
17
+ self.default_queue_name = 'mailer'
18
+ self.excluded_environments = [:test]
19
+
20
+ module ClassMethods
21
+ def current_env
22
+ ::Rails.env
23
+ end
24
+
25
+ def method_missing(method_name, *args)
26
+ return super if environment_excluded?
27
+
28
+ if action_methods.include?(method_name.to_s)
29
+ MessageDecoy.new(self, method_name, *args)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def perform(action, *args)
36
+ self.send(:new, action, *args).message.deliver
37
+ end
38
+
39
+ def environment_excluded?
40
+ !ActionMailer::Base.perform_deliveries || excluded_environment?(current_env)
41
+ end
42
+
43
+ def excluded_environment?(name)
44
+ ::Qu::Mailer.excluded_environments && ::Qu::Mailer.excluded_environments.include?(name.to_sym)
45
+ end
46
+
47
+ def qu
48
+ ::Qu::Mailer.default_queue_target
49
+ end
50
+
51
+ def queue
52
+ ::Qu::Mailer.default_queue_name
53
+ end
54
+
55
+ class MessageDecoy
56
+ def initialize(mailer_class, method_name, *args)
57
+ @mailer_class = mailer_class
58
+ @method_name = method_name
59
+ *@args = *args
60
+ end
61
+
62
+ def qu
63
+ ::Qu::Mailer.default_queue_target
64
+ end
65
+
66
+ def actual_message
67
+ @actual_message ||= @mailer_class.send(:new, @method_name, *@args).message
68
+ end
69
+
70
+ def deliver
71
+ qu.enqueue(@mailer_class, @method_name, *@args)
72
+ end
73
+
74
+ def deliver!
75
+ actual_message.deliver!
76
+ end
77
+
78
+ def method_missing(method_name, *args)
79
+ actual_message.send(method_name, *args)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
data/qu_mailer.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'qu_mailer'
3
+ s.version = '0.1.0'
4
+ s.platform = Gem::Platform::RUBY
5
+
6
+ s.summary = 'Asynchronous email delivery for ActionMailer via Qu'
7
+ s.description = 'QuMailer is a Rails plugin for delivering email asynchronously from ActionMailer via the Qu queuing library.'
8
+
9
+ s.homepage = 'https://github.com/pootsbook/qu_mailer'
10
+ s.authors = ['Philip Poots']
11
+ s.email = ['philip.poots@gmail.com']
12
+
13
+ s.files = [
14
+ 'lib/qu_mailer.rb',
15
+ 'spec/qu_mailer_spec.rb',
16
+ 'spec/spec_helper.rb',
17
+ 'init.rb',
18
+ 'Gemfile',
19
+ 'Gemfile.lock',
20
+ 'README.md',
21
+ 'qu_mailer.gemspec'
22
+ ]
23
+ s.test_files = [
24
+ 'spec/spec_helper.rb',
25
+ 'spec/qu_mailer_spec.rb'
26
+ ]
27
+ s.require_paths = ['lib']
28
+
29
+ s.required_ruby_version = ::Gem::Requirement.new('~> 1.9')
30
+
31
+ s.add_dependency 'qu', '>= 0.1.3'
32
+ s.add_dependency 'actionmailer', '>= 3.0.0'
33
+ s.add_development_dependency 'rspec', '>= 2.6.0'
34
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ class FakeQu
4
+ def self.enqueue(*args); end
5
+ end
6
+
7
+ class Rails3Mailer < ActionMailer::Base
8
+ include Qu::Mailer
9
+ default :from => 'sender@example.org', :subject => 'Subject'
10
+ MAIL_PARAMS = { :to => 'recipient@example.org' }
11
+
12
+ def test_mail(*params)
13
+ Qu::Mailer.success!
14
+ mail(*params)
15
+ end
16
+ end
17
+
18
+ describe Qu::Mailer do
19
+ let(:qu) { FakeQu }
20
+
21
+ before do
22
+ Qu::Mailer.default_queue_target = qu
23
+ Qu::Mailer.stub(:success!)
24
+ Rails3Mailer.stub(:current_env => :test)
25
+ end
26
+
27
+ describe "qu" do
28
+ it "allows overriding of the default queue target (for testing)" do
29
+ Qu::Mailer.default_queue_target = FakeQu
30
+ Rails3Mailer.qu.should == FakeQu
31
+ end
32
+ end
33
+
34
+ describe "queue" do
35
+ it "defaults to the 'mailer' queue" do
36
+ Rails3Mailer.queue.should == "mailer"
37
+ end
38
+
39
+ it "allows overriding of the default queue name" do
40
+ Qu::Mailer.default_queue_name = "postal"
41
+ Rails3Mailer.queue.should == "postal"
42
+ end
43
+
44
+ describe "#deliver" do
45
+ before(:all) do
46
+ @delivery = -> {
47
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).deliver
48
+ }
49
+ end
50
+
51
+ it "delivers the email synchronously" do
52
+ -> { @delivery.call }.should_not change(ActionMailer::Base.deliveries, :size)
53
+ end
54
+
55
+ it "places the deliver action on the Qu 'mailer' queue" do
56
+ qu.should_receive(:enqueue).with(Rails3Mailer, :test_mail, Rails3Mailer::MAIL_PARAMS)
57
+ @delivery.call
58
+ end
59
+
60
+ it "does not invoke the method body more than once" do
61
+ Qu::Mailer.should_not_receive(:success!)
62
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).deliver
63
+ end
64
+
65
+ context "when current environment is excluded" do
66
+ it "does not deliver through Qu for excluded environments" do
67
+ Qu::Mailer.stub(:excluded_environments => [:custom])
68
+ Rails3Mailer.should_receive(:current_env).and_return(:custom)
69
+ qu.should_not_receive(:enqueue)
70
+ @delivery.call
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#deliver!" do
77
+ it "delivers the email synchronously" do
78
+ -> {
79
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).deliver!
80
+ }.should change(ActionMailer::Base.deliveries, :size).by(1)
81
+ end
82
+ end
83
+
84
+ describe "perform" do
85
+ it "performs a queued mailer job" do
86
+ -> {
87
+ Rails3Mailer.perform(:test_mail, Rails3Mailer::MAIL_PARAMS)
88
+ }.should change(ActionMailer::Base.deliveries, :size).by(1)
89
+ end
90
+ end
91
+
92
+ describe "original mail methods" do
93
+ it "is preserved" do
94
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).subject.should == 'Subject'
95
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).from.should include('sender@example.org')
96
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).to.should include('recipient@example.org')
97
+ end
98
+
99
+ it "requires execution of the method body prior to queuing" do
100
+ Qu::Mailer.should_receive(:success!).once
101
+ Rails3Mailer.test_mail(Rails3Mailer::MAIL_PARAMS).subject
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'action_mailer'
4
+ require 'qu_mailer'
5
+
6
+ Qu::Mailer.excluded_environments = []
7
+ ActionMailer::Base.delivery_method = :test
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qu_mailer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Philip Poots
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-13 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: qu
16
+ requirement: &70130676481580 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70130676481580
25
+ - !ruby/object:Gem::Dependency
26
+ name: actionmailer
27
+ requirement: &70130676480700 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70130676480700
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70130676479720 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 2.6.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70130676479720
47
+ description: QuMailer is a Rails plugin for delivering email asynchronously from ActionMailer
48
+ via the Qu queuing library.
49
+ email:
50
+ - philip.poots@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - lib/qu_mailer.rb
56
+ - spec/qu_mailer_spec.rb
57
+ - spec/spec_helper.rb
58
+ - init.rb
59
+ - Gemfile
60
+ - Gemfile.lock
61
+ - README.md
62
+ - qu_mailer.gemspec
63
+ homepage: https://github.com/pootsbook/qu_mailer
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: '1.9'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 1.8.10
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Asynchronous email delivery for ActionMailer via Qu
87
+ test_files:
88
+ - spec/spec_helper.rb
89
+ - spec/qu_mailer_spec.rb