qu_mailer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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