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.
@@ -0,0 +1,168 @@
1
+ require 'base64'
2
+ require 'mime/types'
3
+
4
+ module MandrillQueue
5
+ module Message
6
+ class Attachments
7
+ class Attachment
8
+ ACCESSORS = [:file, :name, :content, :type]
9
+
10
+ def initialize(file = nil, options = {}, &block)
11
+ @options = options
12
+ @file = file
13
+
14
+ if file.is_a?(Hash)
15
+ @options = file
16
+ @file = nil
17
+ end
18
+
19
+ load_file if @options[:load_file] && !@file.nil?
20
+
21
+ instance_eval(&block) if block_given?
22
+ end
23
+
24
+ def file(*args)
25
+ if args.count > 0
26
+ reset!
27
+ @file = args.first
28
+ end
29
+ @file
30
+ end
31
+
32
+ def reset!
33
+ @file = nil
34
+ @type = nil
35
+ @content = nil
36
+ @name = nil
37
+ end
38
+
39
+ def file_loaded?
40
+ !@content.nil?
41
+ end
42
+
43
+ def name(*args)
44
+ @name = args.first if args.count > 0
45
+
46
+ @name ||= (File.basename(@file) unless @file.nil?)
47
+ end
48
+
49
+ def type(*args)
50
+ @type = args.first if args.count > 0
51
+
52
+ @type ||= begin
53
+ unless @file.nil?
54
+ MIME::Types.type_for(@file).first.to_s
55
+ end || "application/octet-stream"
56
+ end
57
+ end
58
+
59
+ def content(*args)
60
+ if args.count > 0
61
+ @content = Base64.encode64(args.first)
62
+ end
63
+ @content
64
+ end
65
+
66
+ def content64(*args)
67
+ @content = args.first if args.count > 0
68
+ @content
69
+ end
70
+
71
+ def load_file
72
+ return false if file_loaded?
73
+
74
+ content(IO.read(@file))
75
+ # set @name and @type if not already set before getting rid of file
76
+ name()
77
+ type()
78
+ @file = nil
79
+ self
80
+ end
81
+
82
+ def validate(errors, options = {})
83
+ options[:as] ||= :attachments
84
+ errors.push([options[:as], "No file or content for attachment '#{name}'."]) if content64.nil? && file.nil?
85
+ errors.push([options[:as], "No attachment name given."]) if name.nil?
86
+ errors.push([options[:as], "File to load (#{file}) does not exist."]) if @file && !file_loaded? && !File.exist?(file)
87
+ end
88
+
89
+ def set!(hash)
90
+ ACCESSORS.each do |key|
91
+ instance_variable_set("@#{key}", hash[key])
92
+ end
93
+
94
+ self
95
+ end
96
+
97
+ def to_hash(options = {})
98
+ hash = {}
99
+
100
+ ACCESSORS.each do |key|
101
+ value = send(key)
102
+ hash[key] = value if options[:include_nils] || !value.nil?
103
+ end
104
+
105
+ hash
106
+ end
107
+
108
+ alias_method :dsl, :instance_eval
109
+ end
110
+
111
+ module DSL
112
+ def attachments(&block)
113
+ @_attachments ||= Attachments.new
114
+ @_attachments.dsl(&block) if block_given?
115
+ block_given? ? self : @_attachments
116
+ end
117
+ end
118
+
119
+ def initialize
120
+ @_attachments = []
121
+ end
122
+
123
+ def add(*args, &block)
124
+ @_attachments << attachment_class.new(*args, &block)
125
+ end
126
+
127
+ def attachment_class
128
+ @_klass ||= Attachment
129
+ end
130
+
131
+ def count
132
+ @_attachments.count
133
+ end
134
+
135
+ def load_all
136
+ @_attachments.each(&:load_file)
137
+ end
138
+
139
+ def to_a(options = {})
140
+ @_attachments.map do |a|
141
+ a.to_hash(options)
142
+ end
143
+ end
144
+
145
+ def set!(list)
146
+ @_attachments = list.map do |obj|
147
+ attachment_class.new.set!(obj.symbolize_keys)
148
+ end
149
+
150
+ self
151
+ end
152
+
153
+ def attachments
154
+ @_attachments
155
+ end
156
+
157
+ def validate(errors, options = {})
158
+ @_attachments.each do |a|
159
+ a.validate(errors, options)
160
+ end
161
+ end
162
+
163
+ alias_method :dsl, :instance_eval
164
+
165
+ Variables::DSL.include_as(self, :vars)
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,37 @@
1
+ require 'mime/types'
2
+ require 'mandrill_queue/message/attachments'
3
+
4
+ module MandrillQueue
5
+ module Message
6
+ class Images < Attachments
7
+ class Image < Attachments::Attachment
8
+ def image_type?
9
+ MIME::Types[/^image/].any? { |m| m == type }
10
+ end
11
+
12
+ def validate(errors, options = {})
13
+ options[:as] ||= :images
14
+ super(errors, options)
15
+
16
+ unless image_type?
17
+ errors.push([options[:as], "Invalid image mime type."])
18
+ end
19
+ end
20
+ end
21
+
22
+ module DSL
23
+ def images(&block)
24
+ @_images ||= Attachments.new
25
+ @_images.dsl(&block) if block_given?
26
+ block_given? ? self : @_images
27
+ end
28
+ end
29
+
30
+ # Override default attachment class
31
+ def attachment_class
32
+ Image
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,24 @@
1
+ require 'mandrill_queue/variables'
2
+ require 'mandrill_queue/message/recipient/data'
3
+ require 'mandrill_queue/message/recipient/variable'
4
+
5
+ module MandrillQueue
6
+ module Message
7
+ class MergeVars < Recipient::Data
8
+
9
+ class Var < Recipient::Variable
10
+ variables :vars
11
+ end
12
+
13
+ var_class Var
14
+
15
+ module DSL
16
+ def merge_vars(*args, &block)
17
+ @_merge_vars ||= MergeVars.new
18
+ @_merge_vars.dsl(*args, &block) if args.count > 0 || block_given?
19
+ block_given? ? self : @_merge_vars
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,149 @@
1
+ require 'mandrill_queue/errors'
2
+ require 'mandrill_queue/variables'
3
+ require 'mandrill_queue/message/recipient/helpers'
4
+
5
+ module MandrillQueue
6
+ module Message
7
+ module Recipient
8
+ class Data
9
+
10
+ def self.inherited(base)
11
+ base.class_eval do
12
+ define_method(base.name.underscore.split('/').last) do
13
+ @_vars
14
+ end
15
+ end
16
+ end
17
+
18
+ def self.var_class(klass = nil)
19
+ @_var_class = klass unless klass.nil?
20
+ @_var_class
21
+ end
22
+
23
+ def register_recipient(email, index)
24
+ raise RecipientDataError, "#{email} has already been registered in recipient index." if recipient_index.has_key?(email)
25
+ recipient_index[email] = index
26
+ end
27
+
28
+ def recipient_index
29
+ @_rcpt_index || clear_recipient_index
30
+ end
31
+
32
+ def clear_recipient_index
33
+ @_rcpt_index = {}
34
+ end
35
+
36
+ def initialize
37
+ @_vars = []
38
+ end
39
+
40
+ def var_class
41
+ self.class.var_class
42
+ end
43
+
44
+ def add(*args, &block)
45
+ recipient = args.first
46
+ if recipient.is_a?(String)
47
+ ind = recipient_index[recipient]
48
+ if ind.nil?
49
+ @_vars << var_class.new(*args, &block)
50
+ register_recipient(recipient, @_vars.count - 1)
51
+ else
52
+ self[ind].variables.dsl(&block)
53
+ end
54
+ elsif recipient.respond_to?(:each)
55
+ add_objects(*args, &block)
56
+ elsif !recipient.nil?
57
+ raise MessageError, "Invalid recipient for #{name}"
58
+ end
59
+ end
60
+
61
+ alias_method :dsl, :add
62
+
63
+ def to_a(options = {})
64
+ @_vars.map do |v|
65
+ v.to_hash(options)
66
+ end
67
+ end
68
+
69
+ def first
70
+ @_vars.first
71
+ end
72
+
73
+ def last
74
+ @_vars.last
75
+ end
76
+
77
+ def [](index)
78
+ @_vars[index]
79
+ end
80
+
81
+ def count
82
+ @_vars.count
83
+ end
84
+
85
+ def validate(errors)
86
+ @_vars.each do |v|
87
+ v.validate(errors)
88
+ end
89
+ end
90
+
91
+ def set!(list)
92
+ @_vars = list.map do |obj|
93
+ var_class.new.set!(obj.symbolize_keys)
94
+ end
95
+
96
+ self
97
+ end
98
+
99
+ protected
100
+
101
+ def add_objects(list, recipient_field = :email, fields = nil, &block)
102
+ if recipient_field.is_a?(Array)
103
+ fields, recipient_field = recipient_field, :email
104
+ end
105
+
106
+ if block_given?
107
+ # if a block is given we want to hand the array over
108
+ # to the block for mapping
109
+ list.each do |obj|
110
+ recipient = obj.send(recipient_field)
111
+ ind = recipient_index[recipient]
112
+ if ind.nil?
113
+ var = var_class.new
114
+ var.recipient = recipient
115
+ var.variables.dsl(obj, &block)
116
+ @_vars << var
117
+ register_recipient(recipient, @_vars.count - 1)
118
+ else
119
+ self[ind].variables.dsl(obj, &block)
120
+ end
121
+ end
122
+ else
123
+ # Include recipient in final var hash if fields not specified
124
+ # or if explicitly added in fields.
125
+ includes_recipient = fields.nil? || fields.include?(recipient_field)
126
+
127
+ fields << recipient_field unless fields.nil? || includes_recipient
128
+
129
+ hashes = Helpers.objects_to_hashes(list, fields)
130
+
131
+ hashes.each do |h|
132
+ recipient = includes_recipient ? h[recipient_field] : h.delete(recipient_field)
133
+ ind = recipient_index[recipient]
134
+ if ind.nil?
135
+ var = var_class.new
136
+ var.recipient = recipient
137
+ var.variables.set!(h)
138
+ @_vars << var
139
+ register_recipient(recipient, @_vars.count - 1)
140
+ else
141
+ self[ind].variables.merge!(h)
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,30 @@
1
+ module MandrillQueue
2
+ module Message
3
+ module Recipient
4
+ module Helpers
5
+ def self.objects_to_hashes(list, fields = nil, options = {})
6
+ try_methods = options[:try_methods] || [:attributes, :to_hash, :to_h]
7
+ hashes = []
8
+ list.each do |obj|
9
+ hashes << if obj.is_a?(Hash)
10
+ fields.nil? ? obj.dup : obj.select { |o| fields.include?(o) }
11
+ elsif fields.nil?
12
+ meth = try_methods.find { |m| obj.respond_to?(m) }
13
+ # Add object result or nil
14
+ unless meth.nil?
15
+ obj.send(meth)
16
+ end
17
+ else
18
+ hash = {}
19
+ fields.each do |f|
20
+ hash[f] = obj.send(f)
21
+ end
22
+ hash
23
+ end
24
+ end
25
+ hashes
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require 'mandrill_queue/errors'
2
+ require 'mandrill_queue/message/recipient/data'
3
+ require 'mandrill_queue/message/recipient/variable'
4
+
5
+ module MandrillQueue
6
+ module Message
7
+ class RecipientMetadata < Recipient::Data
8
+ class Metadatum < Recipient::Variable
9
+ variables :values
10
+ end
11
+
12
+ var_class Metadatum
13
+
14
+ module DSL
15
+ def recipient_metadata(*args, &block)
16
+ @_recipient_metadata ||= RecipientMetadata.new
17
+ @_recipient_metadata.dsl(*args, &block) if block_given? || args.count > 0
18
+ block_given? ? self : @_recipient_metadata
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,72 @@
1
+ module MandrillQueue
2
+ module Message
3
+ module Recipient
4
+ class Variable
5
+ class << self
6
+ attr_reader :var_name
7
+
8
+ def variables(name)
9
+ @var_name = name
10
+ Variables::DSL.include_as(self, name)
11
+ end
12
+ end
13
+
14
+ def initialize(recipient = nil, *args, &block)
15
+ @_recipient = recipient
16
+ dsl(&block) if block_given?
17
+ end
18
+
19
+ def var_name
20
+ self.class.var_name
21
+ end
22
+
23
+ def recipient=(value)
24
+ @_recipient = value
25
+ end
26
+
27
+ def recipient(value = nil)
28
+ @_recipient = value unless value.nil?
29
+ @_recipient
30
+ end
31
+
32
+ def var_instance
33
+ instance_variable_get("@_#{var_name}".to_sym)
34
+ end
35
+
36
+ def variables
37
+ send(var_name)
38
+ end
39
+
40
+ def var_instance_set(value)
41
+ instance_variable_set("@_#{var_name}".to_sym, value)
42
+ end
43
+
44
+ def to_hash(options = {})
45
+ hash = {}
46
+ hash[:rcpt] = recipient if options[:include_nils] || !recipient.nil?
47
+ if options[:include_nils] || var_instance
48
+ hash[var_name] = send(var_name).to_key_value_array(options)
49
+ end
50
+ hash
51
+ end
52
+
53
+ def set!(hash)
54
+ @_recipient = hash[:rcpt]
55
+ var_instance_set(nil)
56
+ send(var_name).set!(hash[var_name]) unless hash[var_name].nil?
57
+ self
58
+ end
59
+
60
+ def dsl(&block)
61
+ send(var_name).dsl(&block)
62
+ end
63
+
64
+ def validate(errors, options = {})
65
+ cn = options[:as] || self.class.name.underscore.split('/').last.to_sym
66
+ errors.push([cn, "Recipient cannot be empty."]) if recipient.blank?
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,179 @@
1
+ require 'mandrill_queue/errors'
2
+ require 'mandrill_queue/message/recipient/helpers'
3
+
4
+ module MandrillQueue
5
+ module Message
6
+ class Recipients
7
+ # Define DSL for inclusion in remote classes
8
+ module DSL
9
+ def recipients
10
+ @_recipients ||= Recipients.new
11
+ end
12
+
13
+ def self.include_as(base, name)
14
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
15
+ def #{name}(email = nil, name = nil, name_field = nil, &block)
16
+ recipients.dsl(email, name, name_field, :#{name}, &block) if !email.nil? || block_given?
17
+ block_given? ? self : recipients
18
+ end
19
+ RUBY
20
+ end
21
+
22
+ def self.included(base)
23
+ [:to, :cc, :bcc].each do |x|
24
+ include_as(base, x)
25
+ end
26
+ end
27
+ end
28
+
29
+ class Recipient
30
+ ACCESSORS = [:type, :name, :email]
31
+
32
+ def initialize(email = nil, name = nil, type = nil, &block)
33
+ @type = type
34
+ @name = name
35
+ @email = email
36
+
37
+ instance_eval(&block) if block_given?
38
+ end
39
+
40
+ ACCESSORS.each do |key|
41
+ define_method key do |*args|
42
+ var_sym = "@#{key}".to_sym
43
+ if args.count > 0
44
+ instance_variable_set(var_sym, args.first)
45
+ args.first
46
+ else
47
+ instance_variable_get(var_sym)
48
+ end
49
+ end
50
+ end
51
+
52
+ def set!(hash)
53
+ ACCESSORS.each do |key|
54
+ instance_variable_set("@#{key}".to_sym, hash[key])
55
+ end
56
+
57
+ self
58
+ end
59
+
60
+ def to_hash(options = {})
61
+ hash = {}
62
+ ACCESSORS.each do |key|
63
+ value = send(key)
64
+ if options[:include_nils] || !value.nil?
65
+ hash[key] = value.nil? ? nil : value.to_s
66
+ end
67
+ end
68
+ hash
69
+ end
70
+
71
+ def validate(errors)
72
+ errors.push([@type, "Email must be set for recipient."]) if email.nil?
73
+ end
74
+
75
+ alias_method :dsl, :instance_exec
76
+ end
77
+
78
+ def initialize
79
+ @_recipients = []
80
+ end
81
+
82
+ def recipients
83
+ @_recipients
84
+ end
85
+
86
+ def empty?
87
+ @_recipients.empty?
88
+ end
89
+
90
+ def add(email = nil, name = nil, name_field = nil, type = nil, &block)
91
+ if email.respond_to?(:each)
92
+ add_objects(email, name, name_field, type, &block)
93
+ elsif !email.is_a?(String)
94
+ add_objects([email], name, name_field, type, &block)
95
+ else
96
+ @_recipients << Recipient.new(email, name, type, &block)
97
+ end
98
+ end
99
+
100
+ alias_method :dsl, :add
101
+
102
+ def to_a(options = {})
103
+ @_recipients.map do |r|
104
+ r.to_hash(options)
105
+ end
106
+ end
107
+
108
+ def first
109
+ @_recipients.first
110
+ end
111
+
112
+ def last
113
+ @_recipients.last
114
+ end
115
+
116
+ def [](index)
117
+ @_recipients[index]
118
+ end
119
+
120
+ def set!(value, type = nil)
121
+ value = [value] unless value.is_a?(Array)
122
+
123
+ @_recipients = value.map do |recipient|
124
+ obj = Recipient.new
125
+
126
+ case recipient
127
+ when String
128
+ obj.email recipient
129
+ raise MessageError, "Must specify a recipient type when calling set! with a string on recipient." if type.nil?
130
+ obj.type type unless type.nil?
131
+ when Hash
132
+ recipient.symbolize_keys!
133
+ raise MessageError, "#{recipient} must contain email address" if recipient[:email].nil?
134
+ obj.set!(recipient)
135
+ obj.type type if obj.type.nil? && !type.nil?
136
+ else
137
+ raise MessageError, "#{recipient} is an invalid recipient."
138
+ end
139
+
140
+ obj
141
+ end
142
+
143
+ self
144
+ end
145
+
146
+ def validate(errors)
147
+ @_recipients.each do |r|
148
+ r.validate(errors)
149
+ end
150
+ end
151
+
152
+ protected
153
+
154
+ def add_object(obj, email_field = :email, name_field = nil, type = nil, &block)
155
+ args.first = [args.first]
156
+ add_objects(*args, &block)
157
+ end
158
+
159
+ def add_objects(list, email_field = :email, name_field = nil, type = nil, &block)
160
+ if block_given?
161
+ list.each do |r|
162
+ obj = Recipient.new
163
+ obj.dsl(r, &block)
164
+ obj.type(type)
165
+ @_recipients << obj
166
+ end
167
+ else
168
+ hashes = MandrillQueue::Message::Recipient::Helpers
169
+ .objects_to_hashes(list, [email_field, name_field].compact)
170
+
171
+ @_recipients += hashes.map do |h|
172
+ Recipient.new(h[email_field], h[name_field], type, &block)
173
+ end
174
+ end
175
+ end
176
+
177
+ end
178
+ end
179
+ end