message_router 0.1.1 → 0.1.2
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.lock +1 -1
- data/lib/message_router/router.rb +11 -3
- data/lib/message_router/version.rb +1 -1
- data/spec/message_router_spec.rb +202 -172
- metadata +4 -4
data/Gemfile.lock
CHANGED
@@ -16,11 +16,17 @@ class MessageRouter
|
|
16
16
|
# Logger.error "Can't reply when when don't know who a message is from: #{env.inspect}"
|
17
17
|
# end
|
18
18
|
#
|
19
|
+
# # Matches if the first word of env['body'] is PING (case insensitive).
|
20
|
+
# # Overwrite #default_attribute in your router to match against a
|
21
|
+
# # different attribute.
|
19
22
|
# match 'ping' do
|
20
23
|
# PingCounter.increment!
|
21
24
|
# send_reply 'pong', env
|
22
25
|
# end
|
23
26
|
#
|
27
|
+
# # Matches if env['body'] matches the given Regexp.
|
28
|
+
# # Overwrite #default_attribute in your router to match against a
|
29
|
+
# # different attribute.
|
24
30
|
# match /\Ahelp/i do
|
25
31
|
# SupportQueue.contact_asap(env['from'])
|
26
32
|
# send_reply 'Looks like you need some help. Hold tight someone will call you soon.', env
|
@@ -271,8 +277,7 @@ class MessageRouter
|
|
271
277
|
|
272
278
|
case should_i
|
273
279
|
when Regexp, String
|
274
|
-
|
275
|
-
normalize_match_params 'body' => should_i
|
280
|
+
normalize_match_params default_attribute => should_i
|
276
281
|
|
277
282
|
when TrueClass, FalseClass, NilClass
|
278
283
|
Proc.new { should_i }
|
@@ -299,7 +304,6 @@ class MessageRouter
|
|
299
304
|
# Assume it already responds to #call.
|
300
305
|
should_i
|
301
306
|
end
|
302
|
-
|
303
307
|
end
|
304
308
|
|
305
309
|
def attr_matches?(attr, val)
|
@@ -316,5 +320,9 @@ class MessageRouter
|
|
316
320
|
raise "Unexpected value '#{val.inspect}'. Should be String, Regexp, or Array of Strings and Regexps."
|
317
321
|
end
|
318
322
|
end
|
323
|
+
|
324
|
+
def default_attribute
|
325
|
+
'body'
|
326
|
+
end
|
319
327
|
end
|
320
328
|
end
|
data/spec/message_router_spec.rb
CHANGED
@@ -3,233 +3,263 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
3
3
|
# TODO: Maybe move this into a sub-directory
|
4
4
|
describe MessageRouter::Router do
|
5
5
|
|
6
|
-
describe
|
6
|
+
describe 'defining matchers' do
|
7
|
+
describe '1st argument' do
|
8
|
+
before do
|
9
|
+
# For use in confirming whether or not a proc was called.
|
10
|
+
$thing_to_match = $did_it_run = nil
|
11
|
+
end
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
let :env do
|
14
|
+
{
|
15
|
+
'body' => 'hello world',
|
16
|
+
'from' => '15554443333',
|
17
|
+
'to' => '12345'
|
18
|
+
}
|
19
|
+
end
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
}
|
21
|
-
end
|
21
|
+
# This needs to be a method (and not memoized by #let) so that
|
22
|
+
# $thing_to_match can change within a test.
|
23
|
+
def router
|
24
|
+
Class.new MessageRouter::Router do
|
25
|
+
match($thing_to_match) { $did_it_run = true }
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
# Using these methods also proves that the message is optionally
|
28
|
+
# passed to helper methods.
|
29
|
+
def always_true
|
30
|
+
env['body'] == 'hello world'
|
31
|
+
end
|
32
|
+
def always_false
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end.new
|
36
|
+
end
|
28
37
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
let :the_test do
|
39
|
+
Proc.new do |opts|
|
40
|
+
$thing_to_match = opts[:true]
|
41
|
+
router.call(env)
|
42
|
+
$did_it_run.should == true
|
43
|
+
$did_it_run = nil # reset for next time
|
44
|
+
|
45
|
+
$thing_to_match = opts[:false]
|
46
|
+
router.call(env)
|
47
|
+
$did_it_run.should == nil
|
48
|
+
$did_it_run = nil # reset for next time
|
38
49
|
end
|
50
|
+
end
|
39
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
router.call(env)
|
44
|
-
$did_it_run.should == true
|
45
|
-
$did_it_run = nil # reset for next time
|
46
|
-
|
47
|
-
$thing_to_match = opts[:false]
|
48
|
-
router.call(env)
|
49
|
-
$did_it_run.should == nil
|
50
|
-
$did_it_run = nil # reset for next time
|
51
|
-
end
|
52
|
-
end
|
52
|
+
it 'accepts a boolean' do
|
53
|
+
the_test.call :true => true, :false => false
|
54
|
+
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
it 'accepts a nil' do
|
57
|
+
# True is just here as a placeholder
|
58
|
+
the_test.call :true => true, :false => nil
|
59
|
+
end
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
it 'accepts a proc which is passed the env' do
|
62
|
+
the_test.call(
|
63
|
+
:true => Proc.new { env['to'] == '12345'},
|
64
|
+
:false => Proc.new { env['to'] == '54321'}
|
65
|
+
)
|
66
|
+
end
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
:false => Proc.new { env['to'] == '54321'}
|
67
|
-
)
|
68
|
-
end
|
68
|
+
it 'accepts a regex to match against the message body' do
|
69
|
+
the_test.call :true => /hello/, :false => /bye bye/
|
70
|
+
end
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
|
72
|
+
it 'accepts a string to match against the 1st word in the message body' do
|
73
|
+
the_test.call :true => 'hello', :false => 'hell'
|
74
|
+
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
context 'the default attribute has been over-written' do
|
77
|
+
let(:router) do
|
78
|
+
Class.new MessageRouter::Router do
|
79
|
+
match('cheese') { env['result'] = 'i found cheese' }
|
80
|
+
match(/bean/) { env['result'] = 'magical fruit' }
|
77
81
|
|
78
|
-
|
79
|
-
|
82
|
+
def default_attribute
|
83
|
+
'tacos'
|
84
|
+
end
|
85
|
+
end.new
|
80
86
|
end
|
81
87
|
|
82
|
-
it 'accepts
|
83
|
-
|
88
|
+
it 'accepts a string to match against the 1st word in the default attribute' do
|
89
|
+
env = { 'tacos' => 'cheese please' }
|
90
|
+
router.call(env).should be_true
|
91
|
+
env['result'].should == 'i found cheese'
|
92
|
+
end
|
93
|
+
it "does not match strings against the 'body' attribute" do
|
94
|
+
env = { 'body' => 'cheese please' }
|
95
|
+
router.call(env).should be_nil
|
84
96
|
end
|
85
97
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
98
|
+
it 'accepts a regex to match against the default attribute' do
|
99
|
+
env = { 'tacos' => 'i like beans a lot' }
|
100
|
+
router.call(env).should be_true
|
101
|
+
env['result'].should == 'magical fruit'
|
102
|
+
end
|
103
|
+
it "does not match regex against the 'body' attribute" do
|
104
|
+
env = { 'body' => 'i like beans a lot' }
|
105
|
+
router.call(env).should be_nil
|
106
|
+
end
|
107
|
+
end
|
95
108
|
|
96
|
-
|
97
|
-
|
98
|
-
|
109
|
+
it 'accepts a symbol which is a method name' do
|
110
|
+
the_test.call :true => :always_true, :false => :always_false
|
111
|
+
end
|
99
112
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
match [true, true] do
|
104
|
-
$run_count += 1
|
105
|
-
nil # Return nil to ensure this matcher failed.
|
106
|
-
end
|
107
|
-
end.new
|
113
|
+
it 'accepts an Array' do
|
114
|
+
the_test.call :true => %w(only one of these needs to be the word hello), :false => %w(none of these match)
|
115
|
+
end
|
108
116
|
|
109
|
-
|
110
|
-
|
117
|
+
describe 'matching an Array' do
|
118
|
+
it "doesn't run the 'do_this' block multiple times if there are multiple matches" do
|
119
|
+
$run_count = 0
|
120
|
+
router = Class.new(MessageRouter::Router) do
|
121
|
+
match [true, true] do
|
122
|
+
$run_count += 1
|
123
|
+
nil # Return nil to ensure this matcher failed.
|
124
|
+
end
|
125
|
+
end.new
|
111
126
|
|
127
|
+
router.call({})
|
128
|
+
$run_count.should == 1
|
112
129
|
end
|
113
130
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
'from' => 'something-else',
|
123
|
-
'to' => '12345'
|
124
|
-
}
|
125
|
-
)
|
126
|
-
end
|
127
|
-
it 'accepts a regex to match against the hash key' do
|
128
|
-
the_test.call(
|
129
|
-
:true => {
|
130
|
-
'from' => /\A1555\d{7}\Z/,
|
131
|
-
'to' => /\A\d{5}\Z/
|
132
|
-
},
|
133
|
-
:false => {
|
134
|
-
'from' => /\A1555\d{7}\Z/,
|
135
|
-
'to' => /i don't match/
|
136
|
-
}
|
137
|
-
)
|
138
|
-
end
|
139
|
-
it 'accepts an Array to match against the hash key' do
|
140
|
-
the_test.call(
|
141
|
-
:true => {
|
142
|
-
'from' => [/i don't match/, 'neither do i', 'but this last one does', /\A1555\d{7}\Z/],
|
143
|
-
'to' => [/i don't match/, 'neither do i', 'but this last one does', /\A\d{5}\Z/]
|
144
|
-
},
|
145
|
-
:false => {
|
146
|
-
'from' => [/\A1555\d{7}\Z/, 'that last one did not match'],
|
147
|
-
'to' => [/i don't match/, 'neither do i']
|
148
|
-
}
|
149
|
-
)
|
150
|
-
end
|
131
|
+
it "returns nil if the 'do_this' block returns nil" do
|
132
|
+
$run_count = 0
|
133
|
+
router = Class.new(MessageRouter::Router) do
|
134
|
+
match [true, true] do
|
135
|
+
$run_count += 1
|
136
|
+
nil # Return nil to ensure this matcher failed.
|
137
|
+
end
|
138
|
+
end.new
|
151
139
|
|
152
|
-
|
153
|
-
$thing_to_match = {'i dont exist' => /.*/}
|
154
|
-
router.call(env)
|
155
|
-
$did_it_run.should == nil
|
156
|
-
$did_it_run = nil # reset for next time
|
157
|
-
end
|
140
|
+
router.call({}).should == nil
|
158
141
|
end
|
142
|
+
|
159
143
|
end
|
160
144
|
|
161
|
-
describe '
|
162
|
-
it 'accepts a
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
145
|
+
describe 'matching a hash' do
|
146
|
+
it 'accepts a string to match against the hash key' do
|
147
|
+
the_test.call(
|
148
|
+
:true => {
|
149
|
+
'from' => '15554443333',
|
150
|
+
'to' => '12345'
|
151
|
+
},
|
152
|
+
:false => {
|
153
|
+
'from' => 'something-else',
|
154
|
+
'to' => '12345'
|
155
|
+
}
|
156
|
+
)
|
169
157
|
end
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
158
|
+
it 'accepts a regex to match against the hash key' do
|
159
|
+
the_test.call(
|
160
|
+
:true => {
|
161
|
+
'from' => /\A1555\d{7}\Z/,
|
162
|
+
'to' => /\A\d{5}\Z/
|
163
|
+
},
|
164
|
+
:false => {
|
165
|
+
'from' => /\A1555\d{7}\Z/,
|
166
|
+
'to' => /i don't match/
|
167
|
+
}
|
168
|
+
)
|
178
169
|
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
match
|
184
|
-
|
185
|
-
|
170
|
+
it 'accepts an Array to match against the hash key' do
|
171
|
+
the_test.call(
|
172
|
+
:true => {
|
173
|
+
'from' => [/i don't match/, 'neither do i', 'but this last one does', /\A1555\d{7}\Z/],
|
174
|
+
'to' => [/i don't match/, 'neither do i', 'but this last one does', /\A\d{5}\Z/]
|
175
|
+
},
|
176
|
+
:false => {
|
177
|
+
'from' => [/\A1555\d{7}\Z/, 'that last one did not match'],
|
178
|
+
'to' => [/i don't match/, 'neither do i']
|
179
|
+
}
|
180
|
+
)
|
186
181
|
end
|
187
182
|
|
188
|
-
it '
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
}.should raise_error(ArgumentError)
|
183
|
+
it 'accepts keys that are missing (but is always false)' do
|
184
|
+
$thing_to_match = {'i dont exist' => /.*/}
|
185
|
+
router.call(env)
|
186
|
+
$did_it_run.should == nil
|
187
|
+
$did_it_run = nil # reset for next time
|
194
188
|
end
|
195
189
|
end
|
190
|
+
end
|
196
191
|
|
197
|
-
|
192
|
+
describe '2nd argument' do
|
193
|
+
it 'accepts a Proc' do
|
198
194
|
env = {}
|
199
195
|
router = Class.new MessageRouter::Router do
|
200
|
-
match { env['did_it_run'] = true }
|
196
|
+
match(true, Proc.new { env['did_it_run'] = true })
|
201
197
|
end.new
|
202
198
|
router.call env
|
203
199
|
env['did_it_run'].should be_true
|
204
200
|
end
|
205
201
|
|
206
|
-
it '
|
202
|
+
it 'accepts a block' do
|
207
203
|
env = {}
|
208
204
|
router = Class.new MessageRouter::Router do
|
209
|
-
match(
|
205
|
+
match(true) { env['did_it_run'] = true }
|
210
206
|
end.new
|
211
207
|
router.call env
|
212
208
|
env['did_it_run'].should be_true
|
213
209
|
end
|
214
210
|
|
215
|
-
it '
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
router.call env
|
222
|
-
env['did_it_run'].should be_true
|
211
|
+
it 'raises an execption when both a Proc and a block are given' do
|
212
|
+
lambda {
|
213
|
+
router = Class.new MessageRouter::Router do
|
214
|
+
match(true, Proc.new { env['did_it_run'] = true }) { env['did_it_run'] = true }
|
215
|
+
end.new
|
216
|
+
}.should raise_error(ArgumentError)
|
223
217
|
end
|
224
218
|
|
225
|
-
it 'raises an execption when
|
219
|
+
it 'raises an execption when neither a Proc nor a block are given' do
|
226
220
|
lambda {
|
227
221
|
router = Class.new MessageRouter::Router do
|
228
|
-
match
|
222
|
+
match true
|
229
223
|
end.new
|
230
224
|
}.should raise_error(ArgumentError)
|
231
225
|
end
|
232
226
|
end
|
227
|
+
|
228
|
+
it 'defaults the 1st argument to true if only a block is given' do
|
229
|
+
env = {}
|
230
|
+
router = Class.new MessageRouter::Router do
|
231
|
+
match { env['did_it_run'] = true }
|
232
|
+
end.new
|
233
|
+
router.call env
|
234
|
+
env['did_it_run'].should be_true
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'defaults the 1st argument to true if only a Proc is given' do
|
238
|
+
env = {}
|
239
|
+
router = Class.new MessageRouter::Router do
|
240
|
+
match(Proc.new { env['did_it_run'] = true })
|
241
|
+
end.new
|
242
|
+
router.call env
|
243
|
+
env['did_it_run'].should be_true
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'accepts a Hash with a symbol as its only key and a Proc as its only value' do
|
247
|
+
env = {}
|
248
|
+
router = Class.new MessageRouter::Router do
|
249
|
+
match :true_method => (Proc.new { env['did_it_run'] = true })
|
250
|
+
def true_method; true; end
|
251
|
+
end.new
|
252
|
+
router.call env
|
253
|
+
env['did_it_run'].should be_true
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'raises an execption when no arguments and no block is given' do
|
257
|
+
lambda {
|
258
|
+
router = Class.new MessageRouter::Router do
|
259
|
+
match
|
260
|
+
end.new
|
261
|
+
}.should raise_error(ArgumentError)
|
262
|
+
end
|
233
263
|
end
|
234
264
|
|
235
265
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: message_router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brad Gessler
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-09-10 00:00:00 Z
|
20
20
|
dependencies: []
|
21
21
|
|
22
22
|
description: a DSL for routing SMS, Twitter, and other short message formats.
|