mandrill_queue 0.1.1
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 +19 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +200 -0
- data/Rakefile +2 -0
- data/lib/mandrill_queue/array_metadata.rb +103 -0
- data/lib/mandrill_queue/configuration.rb +42 -0
- data/lib/mandrill_queue/core_ext.rb +15 -0
- data/lib/mandrill_queue/errors.rb +24 -0
- data/lib/mandrill_queue/logging.rb +51 -0
- data/lib/mandrill_queue/mailer.rb +184 -0
- data/lib/mandrill_queue/mandrill_api.rb +25 -0
- data/lib/mandrill_queue/message/attachments.rb +168 -0
- data/lib/mandrill_queue/message/images.rb +37 -0
- data/lib/mandrill_queue/message/merge_vars.rb +24 -0
- data/lib/mandrill_queue/message/recipient/data.rb +149 -0
- data/lib/mandrill_queue/message/recipient/helpers.rb +30 -0
- data/lib/mandrill_queue/message/recipient/metadata.rb +23 -0
- data/lib/mandrill_queue/message/recipient/variable.rb +72 -0
- data/lib/mandrill_queue/message/recipients.rb +179 -0
- data/lib/mandrill_queue/message.rb +140 -0
- data/lib/mandrill_queue/railtie.rb +20 -0
- data/lib/mandrill_queue/variables.rb +99 -0
- data/lib/mandrill_queue/version.rb +3 -0
- data/lib/mandrill_queue/worker/hooks.rb +21 -0
- data/lib/mandrill_queue/worker.rb +46 -0
- data/lib/mandrill_queue.rb +52 -0
- data/lib/rails/generators/mandrill_queue/initializer_generator.rb +14 -0
- data/lib/rails/generators/mandrill_queue/templates/initializer.rb +36 -0
- data/lib/rails/generators/mandrill_queue/templates/worker/worker.rb +23 -0
- data/lib/rails/generators/mandrill_queue/worker_generator.rb +17 -0
- metadata +205 -0
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :test do
|
6
|
+
gem 'rspec', require: false
|
7
|
+
gem 'guard-rspec', require: false
|
8
|
+
|
9
|
+
gem 'rb-inotify', :require => false
|
10
|
+
gem 'rb-fsevent', :require => false
|
11
|
+
gem 'rb-fchange', :require => false
|
12
|
+
|
13
|
+
gem 'ruby_gntp' if RUBY_PLATFORM =~ /darwin/i
|
14
|
+
gem 'libnotify' if RUBY_PLATFORM =~ /linux/i
|
15
|
+
end
|
16
|
+
|
17
|
+
# group :development, :test do
|
18
|
+
# gem 'debugger', platform: :ruby
|
19
|
+
# end
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Stan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
==========================
|
2
|
+
MandrillQueue::Mailer
|
3
|
+
==========================
|
4
|
+
[](https://travis-ci.org/fixate/mandrill_queue)
|
5
|
+
|
6
|
+
DSL for sending mailers through Mailchimps Mandrill API. This gem enqueues the
|
7
|
+
message on a background worker (`Resque` only for now, but I want to refactor
|
8
|
+
so that it doesnt matter).
|
9
|
+
|
10
|
+
The DSL is modelled on the JSON api [here](https://mandrillapp.com/api/docs/messages.ruby.html#method=send-template).
|
11
|
+
|
12
|
+
## The DSL
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# app/mailers/my_mailer.rb
|
16
|
+
class MyMailer < MandrillQueue::Mailer
|
17
|
+
# Template names are inferred from the class_name (without Mailer) + the method
|
18
|
+
# name. Spaces are `sluggified`. If you want to override the prefixes use:
|
19
|
+
# template_prefix 'my-project'
|
20
|
+
# now templates will be 'my-project' + sluggified method
|
21
|
+
#
|
22
|
+
# template_prefix '' means no prefix will be used
|
23
|
+
|
24
|
+
# Set defaults for all methods here.
|
25
|
+
# The full DSL is available here so feel free to include `merge_vars`,
|
26
|
+
# `preserve_recipients`, `to` etc.
|
27
|
+
# Settings here have a lower precedence than method settings.
|
28
|
+
#
|
29
|
+
defaults do
|
30
|
+
# Setting the default template will disable implicit template names
|
31
|
+
# template 'master_template'
|
32
|
+
message do
|
33
|
+
from_email 'no-reply@mysite.com'
|
34
|
+
end
|
35
|
+
|
36
|
+
content do ... end
|
37
|
+
end
|
38
|
+
|
39
|
+
def welcome_dave
|
40
|
+
template 'welcome'
|
41
|
+
|
42
|
+
message do
|
43
|
+
to 'dave@amazabal.ls', 'Dave' # Name optional
|
44
|
+
cc 'davesmom@yahoo.com'
|
45
|
+
bcc 'daves-sis@gmail.com'
|
46
|
+
|
47
|
+
to [{email: 'another@person.com', name: 'Another'}, ...]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Template content
|
51
|
+
# e.g. <div mc:edit="my_tag"></div>
|
52
|
+
content do
|
53
|
+
my_tag '<p>Content!</p>'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def welcome_many(users)
|
58
|
+
message do
|
59
|
+
# If the given parameter is an array of objects or hashes
|
60
|
+
# that respond_to?/has_key? `email` then we're good to go.
|
61
|
+
# Same goes for `name`. Second and third parameters override this
|
62
|
+
# e.g. to users, :work_email, :fullname
|
63
|
+
to users
|
64
|
+
|
65
|
+
# You can also do your own mapping (to, cc and bcc have the same DSL):
|
66
|
+
cc users do |user|
|
67
|
+
email user.work_email
|
68
|
+
name "#{user.firstname} #{user.lastname}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def message_with_merge_vars(vars) # Template slug: my-message-with-merge-vars
|
74
|
+
message do
|
75
|
+
to 'some@email.com'
|
76
|
+
|
77
|
+
global_merge_vars do ... end
|
78
|
+
global_merge_vars {vars: 'everywhere'}
|
79
|
+
|
80
|
+
# Substitute *|MERGE_VARS|* in your template for given recipients
|
81
|
+
merge_vars 'some@email.com' do
|
82
|
+
key 'value'
|
83
|
+
whatever 'you want'
|
84
|
+
this_will 'only apply to some@email.com'
|
85
|
+
end
|
86
|
+
# If an array of objects/hashes contains an email method or key
|
87
|
+
# that will be used as the recipient and the rest as normal vars.
|
88
|
+
merge_vars vars #, :other_email_field
|
89
|
+
|
90
|
+
track_clicks false
|
91
|
+
end
|
92
|
+
|
93
|
+
# Use send_at/send_in (no difference) to tell Mandrill to delay sending
|
94
|
+
send_in 2.days.from_now
|
95
|
+
end
|
96
|
+
|
97
|
+
def html_message(html)
|
98
|
+
message do
|
99
|
+
# (omitted)
|
100
|
+
html "<html><body>#{html}</html></body>"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Meanwhile in another file...
|
105
|
+
# maybe your controller...
|
106
|
+
# Just like ActionMailer (note the class method calls are handed to instance methods)
|
107
|
+
MyMailer.welcome_many(users).deliver
|
108
|
+
```
|
109
|
+
|
110
|
+
## Installation
|
111
|
+
|
112
|
+
You probably already know this bit:
|
113
|
+
|
114
|
+
gem 'resque' # Support for Sidekiq and writing custom adapters coming soon...
|
115
|
+
gem 'mandrill-queue'
|
116
|
+
|
117
|
+
but didn't know this (but it's optional):
|
118
|
+
|
119
|
+
rails g mandrill_queue:initializer
|
120
|
+
|
121
|
+
Global configuration options are documented in the initializer
|
122
|
+
but heres a taster:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
MandrillQueue.configure do |config|
|
126
|
+
config.queue = :hipster_queue
|
127
|
+
# ...
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
## Setting up the worker
|
132
|
+
|
133
|
+
Run it with a rake task like so:
|
134
|
+
|
135
|
+
rake resque:work QUEUES=mailer
|
136
|
+
|
137
|
+
TODO: I still need to check that everything is OK when running the worker in Rails
|
138
|
+
since I run mine outside Rails as a lightweight worker using:
|
139
|
+
|
140
|
+
rake resque:work -r ./worker.rb QUEUES=mailer
|
141
|
+
|
142
|
+
|
143
|
+
## Devise mailer integration
|
144
|
+
|
145
|
+
Since Mandrill_Queue quacks like ActionMailer where it counts, getting your Devise
|
146
|
+
mailers on Mandrill infrastructure is pretty easy. Here is my implementation:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class DeviseMailer < MandrillResque::Mailer
|
150
|
+
defaults do
|
151
|
+
message do
|
152
|
+
from_email Devise.mailer_sender
|
153
|
+
track_clicks false
|
154
|
+
track_opens false
|
155
|
+
view_content_link false
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Setup a template with the slug: devise-confirmation-instructions
|
160
|
+
def confirmation_instructions(record, token, opts = {})
|
161
|
+
confirm_url = user_confirmation_url(record, confirmation_token: token)
|
162
|
+
devise_mail(record, {name: record.fullname, confirmation_url: confirm_url})
|
163
|
+
end
|
164
|
+
|
165
|
+
# Slug: devise-reset-password-instructions
|
166
|
+
def reset_password_instructions(record, token, opts = {})
|
167
|
+
reset_url = edit_user_password_url(record, reset_password_token: token)
|
168
|
+
devise_mail(record, {name: record.fullname, reset_url: reset_url})
|
169
|
+
end
|
170
|
+
|
171
|
+
# Slug: devise-unlock-instructions
|
172
|
+
def unlock_instructions(record, token, opts = {})
|
173
|
+
unlock_url = user_unlock_url(record, unlock_token: token)
|
174
|
+
devise_mail(record, {name: record.fullname, unlock_url: unlock_url})
|
175
|
+
end
|
176
|
+
|
177
|
+
protected
|
178
|
+
def devise_mail(record, global_vars = {})
|
179
|
+
message do
|
180
|
+
to record, :email, :fullname
|
181
|
+
|
182
|
+
global_merge_vars global_vars
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
## TODO
|
189
|
+
|
190
|
+
1. Refactor so that it can work with `Sidekiq` or a custom adapter - coming soon...
|
191
|
+
2. Allow synchonous sending.
|
192
|
+
2. Render ActionView views to mailers.
|
193
|
+
|
194
|
+
## Contributing
|
195
|
+
|
196
|
+
1. Fork it
|
197
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
198
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
199
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
200
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module MandrillQueue
|
2
|
+
class ArrayMetadata
|
3
|
+
class Var
|
4
|
+
Variables::DSL.include_as(self, :vars)
|
5
|
+
|
6
|
+
def initialize(recipient = nil, &block)
|
7
|
+
@_recipient = recipient
|
8
|
+
dsl(&block) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def recipient=(value)
|
12
|
+
@_recipient = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def recipient(value = nil)
|
16
|
+
@_recipient = value unless value.nil?
|
17
|
+
@_recipient
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash(options = {})
|
21
|
+
hash = {}
|
22
|
+
hash[:rcpt] = recipient if options[:include_nils] || !recipient.nil?
|
23
|
+
hash[:vars] = vars.to_key_value_array(options) if options[:include_nils] || !@_vars.nil?
|
24
|
+
hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def set!(hash)
|
28
|
+
@_recipient = hash[:rcpt]
|
29
|
+
@_vars = nil
|
30
|
+
vars.set!(hash[:vars]) unless hash[:vars].nil?
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def dsl(&block)
|
35
|
+
vars.dsl(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate(errors)
|
39
|
+
errors.push([:merge_vars, "Recipient cannot be empty for merge vars."]) if recipient.blank?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module DSL
|
44
|
+
def merge_vars(recipient = nil, &block)
|
45
|
+
@_merge_vars ||= MergeVars.new
|
46
|
+
@_merge_vars.dsl(recipient, &block) if !recipient.nil? || block_given?
|
47
|
+
block_given? ? self : @_merge_vars
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@_merge_vars = []
|
53
|
+
end
|
54
|
+
|
55
|
+
def add(*args, &block)
|
56
|
+
@_merge_vars << Var.new(*args, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
alias_method :dsl, :add
|
60
|
+
|
61
|
+
def to_a(options = {})
|
62
|
+
@_merge_vars.map do |v|
|
63
|
+
v.to_hash(options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def first
|
68
|
+
@_merge_vars.first
|
69
|
+
end
|
70
|
+
|
71
|
+
def last
|
72
|
+
@_merge_vars.last
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](index)
|
76
|
+
@_merge_vars[index]
|
77
|
+
end
|
78
|
+
|
79
|
+
def count
|
80
|
+
@_merge_vars.count
|
81
|
+
end
|
82
|
+
|
83
|
+
def merge_vars
|
84
|
+
@_merge_vars
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate(errors)
|
88
|
+
@_merge_vars.each do |v|
|
89
|
+
v.validate(errors)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def set!(list)
|
94
|
+
@_merge_vars = list.map do |obj|
|
95
|
+
Var.new.set!(obj.symbolize_keys)
|
96
|
+
end
|
97
|
+
|
98
|
+
self
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module MandrillQueue
|
2
|
+
class Configuration
|
3
|
+
ACCESSORS = [:message_defaults, :resque, :default_worker_class,
|
4
|
+
:default_queue, :api_key, :logger]
|
5
|
+
attr_accessor(*ACCESSORS)
|
6
|
+
|
7
|
+
def initialize(defaults = {}, &block)
|
8
|
+
set(defaults)
|
9
|
+
instance_eval(&block) if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
def []=(key, value)
|
13
|
+
send("#{key}=", value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
send(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
ACCESSORS.each do |key|
|
22
|
+
send("#{key}=", nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
yield self if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_key(&block)
|
29
|
+
ACCESSORS.each(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set(hash)
|
33
|
+
each_key do |k, v|
|
34
|
+
send("#{k}=", hash[k])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.accessors
|
39
|
+
ACCESSORS
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
require 'active_support/core_ext/array'
|
4
|
+
|
5
|
+
class String
|
6
|
+
def sluggify
|
7
|
+
value = self
|
8
|
+
value.gsub!(/[']+/, '')
|
9
|
+
value.gsub!(/\W+/, ' ')
|
10
|
+
value.strip!
|
11
|
+
value.downcase!
|
12
|
+
value.gsub!(/[^A-Za-z0-9]/, '-')
|
13
|
+
value
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module MandrillQueue
|
2
|
+
class Error < ::StandardError; end
|
3
|
+
|
4
|
+
class MandrillValidationError < Error
|
5
|
+
def initialize(errors)
|
6
|
+
@_errors = errors
|
7
|
+
super(message)
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
<<-TXT
|
12
|
+
Validation Errors:
|
13
|
+
#{@_errors.inject(''){ |s, (name, e)| s += "\n- [#{name}]: #{e}" }}
|
14
|
+
TXT
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MessageError < Error; end
|
19
|
+
|
20
|
+
class VariableError < Error; end
|
21
|
+
class VariableNotSetError < VariableError; end
|
22
|
+
|
23
|
+
class RecipientDataError < Error; end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module MandrillQueue
|
5
|
+
module Logging
|
6
|
+
def logging
|
7
|
+
@_logger ||= MandrillQueue.configuration.logger || begin
|
8
|
+
MandrillQueue.resque.constants.include?(:Logging) ? MandrillQueue.resque::Logging : nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def pretty(obj)
|
13
|
+
s = StringIO.new
|
14
|
+
PP.pp(obj, s)
|
15
|
+
s.rewind
|
16
|
+
s.read
|
17
|
+
end
|
18
|
+
|
19
|
+
def result_formatter(r)
|
20
|
+
<<-TXT
|
21
|
+
ID: #{r['_id']}
|
22
|
+
EMAIL: #{r['email']}
|
23
|
+
STATUS: #{r['status']}
|
24
|
+
---
|
25
|
+
TXT
|
26
|
+
end
|
27
|
+
|
28
|
+
def log_results(result)
|
29
|
+
errors = []
|
30
|
+
formatted = result.map do |r|
|
31
|
+
unless ['sent', 'queued'].include?(r['status'])
|
32
|
+
errors << result_formatter(r)
|
33
|
+
end
|
34
|
+
|
35
|
+
result_formatter(r)
|
36
|
+
end
|
37
|
+
|
38
|
+
logging.debug <<-TXT.tr("\t", '')
|
39
|
+
\n*******************************************
|
40
|
+
#{formatted.join("\n")}
|
41
|
+
*******************************************
|
42
|
+
TXT
|
43
|
+
|
44
|
+
if errors.empty?
|
45
|
+
logging.info("#{result.count} message(s) successfully sent.")
|
46
|
+
else
|
47
|
+
logging.error("The following messages were not sent:\n#{errors.join("\n")}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'mandrill_queue'
|
2
|
+
require 'mandrill_queue/errors'
|
3
|
+
require 'mandrill_queue/message'
|
4
|
+
require 'mandrill_queue/variables'
|
5
|
+
|
6
|
+
module MandrillQueue
|
7
|
+
class Mailer
|
8
|
+
class << self
|
9
|
+
def respond_to?(method, include_private = false)
|
10
|
+
super || action_methods.include?(method)
|
11
|
+
end
|
12
|
+
|
13
|
+
def action_methods
|
14
|
+
klass = self
|
15
|
+
klass = klass.superclass until klass == MandrillQueue::Mailer
|
16
|
+
return [] if self == klass
|
17
|
+
self.public_instance_methods(true) -
|
18
|
+
klass.public_instance_methods(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(method, *args)
|
22
|
+
if respond_to?(method)
|
23
|
+
mailer = new(defaults)
|
24
|
+
mailer.send(method, *args)
|
25
|
+
mailer.template(template_from_method(method)) if mailer.template.blank? &&
|
26
|
+
!mailer.message.content_message?
|
27
|
+
mailer
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def configuration
|
34
|
+
MandrillQueue.configuration
|
35
|
+
end
|
36
|
+
|
37
|
+
def defaults(&block)
|
38
|
+
return @_defaults ||= {} unless block_given?
|
39
|
+
|
40
|
+
mailer = new
|
41
|
+
@_in_defaults = true
|
42
|
+
mailer.instance_eval(&block)
|
43
|
+
@_defaults = mailer.to_hash
|
44
|
+
ensure
|
45
|
+
@_in_defaults = false
|
46
|
+
end
|
47
|
+
|
48
|
+
def defaults=(hash)
|
49
|
+
@_defaults = hash
|
50
|
+
end
|
51
|
+
|
52
|
+
def message_defaults
|
53
|
+
md = configuration.message_defaults
|
54
|
+
md.merge!(defaults[:message]) unless @_in_defaults || defaults[:message].nil?
|
55
|
+
md
|
56
|
+
end
|
57
|
+
|
58
|
+
def template_prefix(*args)
|
59
|
+
@template_prefix = args.first unless args.count == 0
|
60
|
+
if @template_prefix.nil?
|
61
|
+
"#{self.name.chomp('Mailer').sluggify}-"
|
62
|
+
else
|
63
|
+
@template_prefix
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def all_templates
|
68
|
+
action_methods.map do |method|
|
69
|
+
template_from_method(method)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def template_from_method(method)
|
75
|
+
template = defaults[:template].blank? ? method.to_s.sluggify : defaults[:template]
|
76
|
+
template_prefix + template
|
77
|
+
end
|
78
|
+
end # End Singleton
|
79
|
+
|
80
|
+
ACCESSORS = [:template, :send_at]
|
81
|
+
|
82
|
+
def initialize(values = nil)
|
83
|
+
set!(values) unless values.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
def reset!
|
87
|
+
ACCESSORS.each do |key|
|
88
|
+
instance_variable_set("@#{key}", nil)
|
89
|
+
end
|
90
|
+
@_message = nil
|
91
|
+
@_content = nil
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def message(&block)
|
96
|
+
@_message ||= Message::Internal.new(self.class.message_defaults)
|
97
|
+
@_message.dsl(&block) if block_given?
|
98
|
+
block_given? ? self : @_message
|
99
|
+
end
|
100
|
+
|
101
|
+
# Define setters
|
102
|
+
ACCESSORS.each do |key|
|
103
|
+
define_method key do |value = nil|
|
104
|
+
var = "@#{key}".to_sym
|
105
|
+
if value.nil?
|
106
|
+
instance_variable_get(var)
|
107
|
+
else
|
108
|
+
instance_variable_set(var, value)
|
109
|
+
self
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
alias :send_in :send_at
|
115
|
+
|
116
|
+
def worker_class
|
117
|
+
self.class.configuration.default_worker_class || ::MandrillQueue::Worker
|
118
|
+
end
|
119
|
+
|
120
|
+
def queue
|
121
|
+
@_queue ||= \
|
122
|
+
|
123
|
+
if instance_variable_defined?(:@queue)
|
124
|
+
instance_variable_get(:@queue)
|
125
|
+
elsif worker_class.instance_variable_defined?(:@queue)
|
126
|
+
worker_class.instance_variable_get(:@queue)
|
127
|
+
elsif worker_class.respond_to?(:queue)
|
128
|
+
worker_class.queue
|
129
|
+
else
|
130
|
+
self.class.configuration.default_queue || :mailer
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def deliver
|
135
|
+
validate!
|
136
|
+
MandrillQueue.resque.enqueue_to(queue, worker_class, to_hash)
|
137
|
+
end
|
138
|
+
|
139
|
+
def to_hash(options = {})
|
140
|
+
hash = {}
|
141
|
+
ACCESSORS.each do |key|
|
142
|
+
value = instance_variable_get("@#{key}".to_sym)
|
143
|
+
hash[key] = value if options[:include_nil] || !value.nil?
|
144
|
+
end
|
145
|
+
|
146
|
+
hash[:message] = message.to_hash(options) rescue nil if !@_message.nil? || options[:include_nils]
|
147
|
+
hash[:content] = content.to_key_value_array(options) rescue nil if !@_content.nil? || options[:include_nils]
|
148
|
+
hash
|
149
|
+
end
|
150
|
+
|
151
|
+
def set!(hash)
|
152
|
+
hash.symbolize_keys!
|
153
|
+
ACCESSORS.each do |key|
|
154
|
+
instance_variable_set("@#{key}", hash[key])
|
155
|
+
end
|
156
|
+
|
157
|
+
message.set!(hash[:message]) unless hash[:message].nil?
|
158
|
+
content.set!(hash[:content]) unless hash[:content].nil?
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
162
|
+
alias_method :dsl, :instance_eval
|
163
|
+
|
164
|
+
def use_defaults!
|
165
|
+
set!(self.class.defaults) unless self.class.defaults.nil?
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
def validate!
|
170
|
+
errors = []
|
171
|
+
message.validate(errors) unless @_message.nil?
|
172
|
+
|
173
|
+
raise MandrillValidationError.new(errors) unless errors.empty?
|
174
|
+
self
|
175
|
+
end
|
176
|
+
|
177
|
+
# Include variable DSL at end of class
|
178
|
+
Variables::DSL.include_as(self, :content)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
if defined?(ActiveSupport)
|
183
|
+
ActiveSupport.run_load_hooks(:mandrill_queue, MandrillQueue::Mailer)
|
184
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mandrill'
|
2
|
+
require 'mandrill_queue'
|
3
|
+
|
4
|
+
module MandrillQueue
|
5
|
+
module MandrillApi
|
6
|
+
class Error < ::StandardError; end
|
7
|
+
|
8
|
+
def configuration
|
9
|
+
MandrillQueue.configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def mandrill
|
13
|
+
@_api ||= begin
|
14
|
+
if configuration.api_key.nil?
|
15
|
+
raise MandrillQueue::Api::Error, <<-ERR
|
16
|
+
An Api key has not been configured. Please configure on as follows in an initializer:
|
17
|
+
MandrillQueue.configure do { |c| c.api_key = 'xxxxxxxxxxxxxx' }
|
18
|
+
ERR
|
19
|
+
end
|
20
|
+
|
21
|
+
Mandrill::API.new(configuration.api_key)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|