outbox 0.1.0 → 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0b94d8233a2c331495060c6d33e8e94b2d3d0cae
4
+ data.tar.gz: eb43a9e7d7b3ced480238c6b47ac0ca6eb5af721
5
+ SHA512:
6
+ metadata.gz: 14d61db45eff14c42092302401dd1317bfeffb13fa500f3ad86f7d387b3a766049b36dcf69e525e63f3c9f6605c34d8e2d87cfe217bd67f7da40d712cd19b9a1
7
+ data.tar.gz: 5fcf9d9938dbece72b956402b0644a08b7c7bb7dd2ec51d36b16c49d3aa7cc1e1d677b246b18b81fe02b12e7311181adbc42de07110849e2af03b1a3dffb21ce
data/lib/outbox.rb CHANGED
@@ -3,6 +3,7 @@ module Outbox
3
3
  require 'outbox/version'
4
4
 
5
5
  autoload 'Accessor', 'outbox/accessor'
6
+ autoload 'DefineInheritableMethod', 'outbox/define_inheritable_method'
6
7
  autoload 'Message', 'outbox/message'
7
8
  autoload 'MessageClients', 'outbox/message_clients'
8
9
  autoload 'MessageFields', 'outbox/message_fields'
@@ -0,0 +1,25 @@
1
+ module Outbox
2
+ module DefineInheritableMethod
3
+ # Similar to .define_method, but adds a dynamic module in the inheritance
4
+ # change to attach the method to. See:
5
+ #
6
+ # http://thepugautomatic.com/2013/07/dsom/
7
+ def define_inheritable_method(mod_name, *args, &block)
8
+ mod = get_inheritable_module(mod_name)
9
+ mod.module_eval do
10
+ define_method(*args, &block)
11
+ end
12
+ end
13
+
14
+ protected
15
+
16
+ def get_inheritable_module(mod_name)
17
+ if const_defined?(mod_name, _search_ancestors = false)
18
+ mod = const_get(mod_name)
19
+ else
20
+ mod = const_set(mod_name, Module.new)
21
+ include mod
22
+ end
23
+ end
24
+ end
25
+ end
@@ -23,6 +23,15 @@ module Outbox
23
23
  end
24
24
  end
25
25
 
26
+ # Loops through each registered message type and sets the content body.
27
+ def body(value)
28
+ each_message_type do |message_type, message|
29
+ next if message.nil?
30
+ message.body = value
31
+ end
32
+ end
33
+ alias :body= :body
34
+
26
35
  # Delivers all of the messages to the given 'audience'. An 'audience' object
27
36
  # can be a hash or an object that responds to the current message types. Only
28
37
  # the message types specified in the 'audience' object will be sent to.
@@ -35,8 +44,7 @@ module Outbox
35
44
  def deliver(audience)
36
45
  audience = Outbox::Accessor.new(audience)
37
46
 
38
- self.class.message_types.each_key do |message_type|
39
- message = self.public_send(message_type)
47
+ each_message_type do |message_type, message|
40
48
  next if message.nil?
41
49
 
42
50
  recipient = audience[message_type]
@@ -1,10 +1,13 @@
1
1
  module Outbox
2
2
  module MessageFields
3
3
  def self.included(base)
4
+ base.extend Outbox::DefineInheritableMethod
4
5
  base.extend ClassMethods
5
6
  end
6
7
 
7
8
  module ClassMethods
9
+ DYNAMIC_MODULE_NAME = :DynamicFields
10
+
8
11
  # Sets default values for defined fields.
9
12
  #
10
13
  # Email.defaults from: 'bob@example.com'
@@ -123,7 +126,7 @@ module Outbox
123
126
  protected
124
127
 
125
128
  def define_field_reader(name)
126
- define_method(name) do |value = nil|
129
+ define_inheritable_method(DYNAMIC_MODULE_NAME, name) do |value = nil|
127
130
  if value.nil?
128
131
  @fields[name]
129
132
  else
@@ -133,7 +136,7 @@ module Outbox
133
136
  end
134
137
 
135
138
  def define_field_writer(name)
136
- define_method("#{name}=") do |value|
139
+ define_inheritable_method(DYNAMIC_MODULE_NAME, "#{name}=") do |value|
137
140
  @fields[name] = value
138
141
  end
139
142
  end
@@ -1,10 +1,13 @@
1
1
  module Outbox
2
2
  module MessageTypes
3
3
  def self.included(base)
4
+ base.extend Outbox::DefineInheritableMethod
4
5
  base.extend ClassMethods
5
6
  end
6
7
 
7
8
  module ClassMethods
9
+ DYNAMIC_MODULE_NAME = :DynamicMessageTypes
10
+
8
11
  # Registers a message type for sending & creates accessors.
9
12
  #
10
13
  # Message.register_message_type :telepathy, TelepathyMessage
@@ -23,6 +26,7 @@ module Outbox
23
26
  message_types[name.to_sym] = message_type
24
27
  define_message_type_reader(name, message_type)
25
28
  define_message_type_writer(name)
29
+ define_default_message_type_client_accessor(name, message_type)
26
30
  end
27
31
 
28
32
  # Returns a hash of the registred message types, where the key is the name
@@ -35,28 +39,51 @@ module Outbox
35
39
 
36
40
  def define_message_type_reader(name, message_type)
37
41
  ivar_name = "@#{name}"
38
- define_method(name) do |options = nil, &block|
39
- if options || block
40
- instance_variable_set(ivar_name, message_type.new(options, &block))
41
- else
42
- instance_variable_get(ivar_name)
42
+ define_inheritable_method(DYNAMIC_MODULE_NAME, name) do |fields = nil, &block|
43
+ instance = instance_variable_get(ivar_name)
44
+
45
+ if instance.nil? && (fields || block)
46
+ instance = message_type.new
47
+ instance_variable_set(ivar_name, instance)
48
+ end
49
+
50
+ if block
51
+ instance.instance_eval(&block)
52
+ elsif fields
53
+ instance.fields = fields
43
54
  end
55
+
56
+ instance
44
57
  end
45
58
  end
46
59
 
47
60
  def define_message_type_writer(name)
48
- define_method("#{name}=") do |value|
61
+ define_inheritable_method(DYNAMIC_MODULE_NAME, "#{name}=") do |value|
49
62
  instance_variable_set("@#{name}", value)
50
63
  end
51
64
  end
52
- end
53
65
 
54
- protected
66
+ def define_default_message_type_client_accessor(name, message_type)
67
+ define_singleton_method "default_#{name}_client" do |*args|
68
+ message_type.default_client(*args)
69
+ end
70
+ end
71
+ end
55
72
 
73
+ # Assign the given hash where each key is a message type and
74
+ # the value is a hash of options for that message type.
56
75
  def assign_message_type_values(values)
57
76
  values.each do |key, value|
58
77
  self.public_send(key, value) if self.respond_to?(key)
59
78
  end
60
79
  end
80
+
81
+ # Loops through each registered message type and yields the instance
82
+ # of that type on this message.
83
+ def each_message_type
84
+ self.class.message_types.each_key do |message_type|
85
+ yield message_type, self.public_send(message_type)
86
+ end
87
+ end
61
88
  end
62
89
  end
@@ -34,6 +34,12 @@ module Outbox
34
34
  self.to = audience if self.respond_to?(:to=)
35
35
  end
36
36
 
37
+ # Sets the 'body' for this message. All message types must implement
38
+ # this method.
39
+ def body=(body)
40
+ raise NotImplementedError, 'Subclasses must implement a body= method'
41
+ end
42
+
37
43
  # Validates the current message and delivers the message using the
38
44
  # defined client.
39
45
  def deliver(audience = nil)
@@ -39,7 +39,9 @@ module Outbox
39
39
  :resent_message_id, :resent_sender, :resent_to, :return_path,
40
40
  :sender, :to, :comments, :subject, accessor: false
41
41
 
42
- def initialize(fields = nil, &block)
42
+ undef :body=, :[], :[]=
43
+
44
+ def initialize(fields = nil, &block) # :nodoc:
43
45
  @message = ::Mail::Message.new
44
46
  super
45
47
  end
@@ -49,7 +51,7 @@ module Outbox
49
51
  @message
50
52
  end
51
53
 
52
- def audience=(audience)
54
+ def audience=(audience) # :nodoc:
53
55
  case audience
54
56
  when String, Array
55
57
  self.to = audience
@@ -61,6 +63,8 @@ module Outbox
61
63
  end
62
64
  end
63
65
 
66
+ protected
67
+
64
68
  def method_missing(method, *args, &block)
65
69
  if @message.respond_to?(method)
66
70
  @message.public_send(method, *args, &block)
@@ -70,7 +74,7 @@ module Outbox
70
74
  end
71
75
 
72
76
  def respond_to_missing?(method, include_private = false)
73
- @message.respond_to?(method, include_private) || super
77
+ super || @message.respond_to?(method, include_private)
74
78
  end
75
79
  end
76
80
  end
@@ -1,3 +1,3 @@
1
1
  module Outbox
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -1,20 +1,20 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Outbox::Clients::Base do
4
- class Client < Outbox::Clients::Base
4
+ class BaseClient < Outbox::Clients::Base
5
5
  defaults foo: 10
6
6
  end
7
7
 
8
8
  describe '.defaults' do
9
9
  it 'defines default settings' do
10
- client = Client.new
10
+ client = BaseClient.new
11
11
  expect(client.settings[:foo]).to eq(10)
12
12
  end
13
13
  end
14
14
 
15
15
  describe '.new' do
16
16
  it 'initializes settings' do
17
- client = Client.new foo: 1, bar: 2
17
+ client = BaseClient.new foo: 1, bar: 2
18
18
  expect(client.settings[:foo]).to eq(1)
19
19
  expect(client.settings[:bar]).to eq(2)
20
20
  end
@@ -22,7 +22,7 @@ describe Outbox::Clients::Base do
22
22
 
23
23
  describe '#deliver' do
24
24
  it 'raises an error' do
25
- client = Client.new
25
+ client = BaseClient.new
26
26
  expect{client.deliver(Outbox::Messages::Base.new)}.to raise_error(NotImplementedError)
27
27
  end
28
28
  end
@@ -4,11 +4,19 @@ describe Outbox::Message do
4
4
  class Telepathy < Outbox::Messages::Base
5
5
  default_client :test
6
6
  fields :to, :from, :thought
7
+
8
+ def body=(value)
9
+ self.thought = value
10
+ end
7
11
  end
8
12
 
9
13
  class MessageInABottle < Outbox::Messages::Base
10
14
  default_client :test
11
15
  fields :to, :bottle, :message
16
+
17
+ def body=(value)
18
+ self.message = value
19
+ end
12
20
  end
13
21
 
14
22
  before do
@@ -63,6 +71,68 @@ describe Outbox::Message do
63
71
  end
64
72
  end
65
73
 
74
+ describe 'default message type client' do
75
+ after do
76
+ Telepathy.registered_client_aliases.delete(:foo)
77
+ Telepathy.default_client :test
78
+ end
79
+
80
+ it 'sets the default client for that message type' do
81
+ client_class = Class.new
82
+ Telepathy.register_client_alias :foo, client_class
83
+ client = double :client
84
+ options = { option_1: 1, option_2: 2 }
85
+ expect(client_class).to receive(:new).with(options) { client}
86
+ Outbox::Message.default_telepathy_client :foo, options
87
+ expect(Telepathy.default_client).to be(client)
88
+ end
89
+ end
90
+
91
+ describe 'message type reader' do
92
+ context 'when uninitialized' do
93
+ it 'returns nil' do
94
+ expect(Outbox::Message.new.telepathy).to be_nil
95
+ end
96
+
97
+ context 'with a hash' do
98
+ it 'creates a new instance' do
99
+ message = Outbox::Message.new
100
+ message.telepathy thought: 'What?'
101
+ expect(message.telepathy.thought).to eq('What?')
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'when initialized' do
107
+ before do
108
+ @message = Outbox::Message.new do
109
+ telepathy do
110
+ from 'Bob'
111
+ thought 'What?'
112
+ end
113
+ end
114
+ end
115
+
116
+ context 'with a hash' do
117
+ it 'applies the fields values' do
118
+ @message.telepathy thought: 'Hello world.'
119
+ expect(@message.telepathy.from).to eq('Bob')
120
+ expect(@message.telepathy.thought).to eq('Hello world.')
121
+ end
122
+ end
123
+
124
+ context 'with a block' do
125
+ it 'applies the fields values' do
126
+ @message.telepathy do
127
+ thought 'Hello world.'
128
+ end
129
+ expect(@message.telepathy.from).to eq('Bob')
130
+ expect(@message.telepathy.thought).to eq('Hello world.')
131
+ end
132
+ end
133
+ end
134
+ end
135
+
66
136
  describe '#deliver' do
67
137
  before do
68
138
  @message = Outbox::Message.new do
@@ -100,4 +170,18 @@ describe Outbox::Message do
100
170
  end
101
171
  end
102
172
  end
173
+
174
+ describe '#body' do
175
+ it 'assigns the value to all message types' do
176
+ message = Outbox::Message.new do
177
+ email {}
178
+ telepathy {}
179
+ bottle {}
180
+ body 'Simple Message'
181
+ end
182
+ expect(message.email.body.encoded).to eq('Simple Message')
183
+ expect(message.telepathy.thought).to eq('Simple Message')
184
+ expect(message.bottle.message).to eq('Simple Message')
185
+ end
186
+ end
103
187
  end
@@ -19,37 +19,19 @@ describe Outbox::Messages::Base do
19
19
  end
20
20
 
21
21
  class MessageWithoutFieldAccessors < Outbox::Messages::Base
22
- attr_reader :to_reader_called, :to_writer_called,
23
- :from_reader_called, :from_writer_called,
24
- :body_reader_called, :body_writer_called
25
-
26
22
  def to(value = nil)
27
- @to_reader_called = true
28
23
  value ? @to = value : @to
29
24
  end
30
25
 
31
26
  def to=(value)
32
- @to_writer_called = true
33
27
  @to = value
34
28
  end
35
29
 
36
30
  def from(value = nil)
37
- @from_reader_called = true
38
31
  value ? @fields[:from] = value : @fields[:from]
39
32
  end
40
33
 
41
- def from=(value)
42
- @from_writer_called = true
43
- @fields[:from] = value
44
- end
45
-
46
- def body
47
- @body_reader_called = true
48
- @fields[:body]
49
- end
50
-
51
34
  def body=(value)
52
- @body_writer_called = true
53
35
  @fields[:body] = value
54
36
  end
55
37
 
@@ -74,11 +56,11 @@ describe Outbox::Messages::Base do
74
56
  after { Message.default_client :test }
75
57
 
76
58
  it 'registers a client alias' do
77
- Client = Class.new
78
- Message.register_client_alias :foo, Client
59
+ client_class = Class.new
60
+ Message.register_client_alias :foo, client_class
79
61
  client = double :client
80
62
  options = { option_1: 1, option_2: 2 }
81
- expect(Client).to receive(:new).with(options) { client}
63
+ expect(client_class).to receive(:new).with(options) { client}
82
64
  Message.default_client :foo, options
83
65
  expect(Message.default_client).to be(client)
84
66
  end
@@ -101,19 +83,11 @@ describe Outbox::Messages::Base do
101
83
  end
102
84
 
103
85
  it 'does not create accessors if specified' do
104
- message = MessageWithoutFieldAccessors.new
105
- message.to = 'Bob'
106
- message.from = 'John'
107
- message.body = 'Hi'
108
- expect(message.to).to eq('Bob')
109
- expect(message.from).to eq('John')
110
- expect(message.body).to eq('Hi')
111
- expect(message.to_reader_called).to be_true
112
- expect(message.to_writer_called).to be_true
113
- expect(message.from_reader_called).to be_true
114
- expect(message.from_writer_called).to be_false
115
- expect(message.body_reader_called).to be_false
116
- expect(message.body_writer_called).to be_true
86
+ dynamic_methods = MessageWithoutFieldAccessors::DynamicFields.public_instance_methods
87
+ expect(dynamic_methods).not_to include(:to=)
88
+ expect(dynamic_methods).not_to include(:to)
89
+ expect(dynamic_methods).not_to include(:from)
90
+ expect(dynamic_methods).not_to include(:body=)
117
91
  end
118
92
  end
119
93
 
@@ -176,6 +150,14 @@ describe Outbox::Messages::Base do
176
150
  end
177
151
  end
178
152
 
153
+ describe '#body=' do
154
+ it 'raises an error' do
155
+ message_type = Class.new Outbox::Messages::Base
156
+ message = message_type.new
157
+ expect{message.body = 'Something'}.to raise_error(NotImplementedError)
158
+ end
159
+ end
160
+
179
161
  describe '#deliver' do
180
162
  context 'when valid' do
181
163
  it 'delivers the message using a client' do
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: outbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Pete Browne
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-07-31 00:00:00.000000000 Z
11
+ date: 2013-08-01 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: mail
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bundler
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,49 +41,43 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rake
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: rspec
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: rspec_junit_formatter
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  description: A generic interface for sending email, SMS, & push notifications.
@@ -109,6 +98,7 @@ files:
109
98
  - lib/outbox/clients/base.rb
110
99
  - lib/outbox/clients/mail_client.rb
111
100
  - lib/outbox/clients/test_client.rb
101
+ - lib/outbox/define_inheritable_method.rb
112
102
  - lib/outbox/errors.rb
113
103
  - lib/outbox/message.rb
114
104
  - lib/outbox/message_clients.rb
@@ -130,33 +120,26 @@ files:
130
120
  homepage: https://github.com/localmed/outbox
131
121
  licenses:
132
122
  - MIT
123
+ metadata: {}
133
124
  post_install_message:
134
125
  rdoc_options: []
135
126
  require_paths:
136
127
  - lib
137
128
  required_ruby_version: !ruby/object:Gem::Requirement
138
- none: false
139
129
  requirements:
140
- - - ! '>='
130
+ - - '>='
141
131
  - !ruby/object:Gem::Version
142
132
  version: '0'
143
- segments:
144
- - 0
145
- hash: -1152741713307649410
146
133
  required_rubygems_version: !ruby/object:Gem::Requirement
147
- none: false
148
134
  requirements:
149
- - - ! '>='
135
+ - - '>='
150
136
  - !ruby/object:Gem::Version
151
137
  version: '0'
152
- segments:
153
- - 0
154
- hash: -1152741713307649410
155
138
  requirements: []
156
139
  rubyforge_project:
157
- rubygems_version: 1.8.23
140
+ rubygems_version: 2.0.3
158
141
  signing_key:
159
- specification_version: 3
142
+ specification_version: 4
160
143
  summary: Outbox is a generic interface for sending notifications using a variety of
161
144
  protocols, with built-in support for the most popular SaaS solutions.
162
145
  test_files: