mandrill_queue 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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