message_router 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 41cf9f1df6c11508d36a7dda6cce51a70ba19f30
4
+ data.tar.gz: 8168d00903f7ee8255021d28c251876e56a9787c
5
+ SHA512:
6
+ metadata.gz: 5f6ea5ea859997e69e646bb65d3505a2d7f65b51a73f22a3613bf91970fbf2890cc9ef99253f482b6ea9c424d6fd85c6ceb3a41ab16d43f3192b5befefb035fc
7
+ data.tar.gz: 9f06de8f00cce839914fdce6ed191e84c447d03ab0687ba948d2fb791943cb2428859efd7a06260ed0638b962f5d85ea45b1e2e2a5679e0af80d03c277e0078a
@@ -0,0 +1 @@
1
+ 2.1.2
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - ree
5
+ - 1.8.7
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - 2.1.3
9
+
10
+ bundler_args: --without test development
data/Gemfile CHANGED
@@ -1,12 +1,16 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in message_router.gemspec
4
4
  gemspec
5
5
 
6
- group :test, :development do
6
+ group :ci, :test, :development do
7
7
  gem 'rspec'
8
- gem 'rb-fsevent'
8
+ gem 'rake'
9
+ end
10
+
11
+ group :test, :development do
12
+ gem 'listen'
9
13
  gem 'growl'
10
14
  gem 'guard'
11
15
  gem 'guard-rspec'
12
- end
16
+ end
@@ -1,27 +1,58 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- message_router (0.1.2)
4
+ message_router (0.2.0)
5
5
 
6
6
  GEM
7
- remote: http://rubygems.org/
7
+ remote: https://rubygems.org/
8
8
  specs:
9
- diff-lcs (1.1.2)
9
+ celluloid (0.16.0)
10
+ timers (~> 4.0.0)
11
+ coderay (1.1.0)
12
+ diff-lcs (1.2.5)
13
+ ffi (1.9.6)
14
+ formatador (0.2.5)
10
15
  growl (1.0.3)
11
- guard (0.5.1)
12
- thor (~> 0.14.6)
13
- guard-rspec (0.4.0)
14
- guard (>= 0.4.0)
15
- rb-fsevent (0.4.2)
16
- rspec (2.6.0)
17
- rspec-core (~> 2.6.0)
18
- rspec-expectations (~> 2.6.0)
19
- rspec-mocks (~> 2.6.0)
20
- rspec-core (2.6.4)
21
- rspec-expectations (2.6.0)
22
- diff-lcs (~> 1.1.2)
23
- rspec-mocks (2.6.0)
24
- thor (0.14.6)
16
+ guard (2.6.1)
17
+ formatador (>= 0.2.4)
18
+ listen (~> 2.7)
19
+ lumberjack (~> 1.0)
20
+ pry (>= 0.9.12)
21
+ thor (>= 0.18.1)
22
+ guard-rspec (4.3.1)
23
+ guard (~> 2.1)
24
+ rspec (>= 2.14, < 4.0)
25
+ hitimes (1.2.2)
26
+ listen (2.7.11)
27
+ celluloid (>= 0.15.2)
28
+ rb-fsevent (>= 0.9.3)
29
+ rb-inotify (>= 0.9)
30
+ lumberjack (1.0.9)
31
+ method_source (0.8.2)
32
+ pry (0.10.1)
33
+ coderay (~> 1.1.0)
34
+ method_source (~> 0.8.1)
35
+ slop (~> 3.4)
36
+ rake (10.3.2)
37
+ rb-fsevent (0.9.4)
38
+ rb-inotify (0.9.5)
39
+ ffi (>= 0.5.0)
40
+ rspec (3.1.0)
41
+ rspec-core (~> 3.1.0)
42
+ rspec-expectations (~> 3.1.0)
43
+ rspec-mocks (~> 3.1.0)
44
+ rspec-core (3.1.7)
45
+ rspec-support (~> 3.1.0)
46
+ rspec-expectations (3.1.2)
47
+ diff-lcs (>= 1.2.0, < 2.0)
48
+ rspec-support (~> 3.1.0)
49
+ rspec-mocks (3.1.3)
50
+ rspec-support (~> 3.1.0)
51
+ rspec-support (3.1.2)
52
+ slop (3.6.0)
53
+ thor (0.19.1)
54
+ timers (4.0.1)
55
+ hitimes
25
56
 
26
57
  PLATFORMS
27
58
  ruby
@@ -30,6 +61,7 @@ DEPENDENCIES
30
61
  growl
31
62
  guard
32
63
  guard-rspec
64
+ listen
33
65
  message_router!
34
- rb-fsevent
66
+ rake
35
67
  rspec
data/Guardfile CHANGED
@@ -1,8 +1,32 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- guard 'rspec', :version => 2, :cli => '--colour', :notification => true do
5
- watch(%r{^spec/.+_spec\.rb})
6
- watch(%r{^lib/(.+)\.rb}) { |m| "spec/message_router_spec.rb" }
7
- watch(/^spec\/spec_helper.rb/) { "spec" }
8
- end
4
+ # Note: The cmd option is now required due to the increasing number of ways
5
+ # rspec may be run, below are examples of the most common uses.
6
+ # * bundler: 'bundle exec rspec'
7
+ # * bundler binstubs: 'bin/rspec'
8
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
9
+ # installed the spring binstubs per the docs)
10
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
11
+ # * 'just' rspec: 'rspec'
12
+ guard :rspec, cmd: 'bundle exec rspec' do
13
+ watch(%r{^spec/.+_spec\.rb$})
14
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
15
+ watch('spec/spec_helper.rb') { "spec" }
16
+
17
+ # Rails example
18
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
19
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
20
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
21
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
22
+ watch('config/routes.rb') { "spec/routing" }
23
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
24
+ watch('spec/rails_helper.rb') { "spec" }
25
+
26
+ # Capybara features specs
27
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
28
+
29
+ # Turnip features and steps
30
+ watch(%r{^spec/acceptance/(.+)\.feature$})
31
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
32
+ end
@@ -1,5 +1,8 @@
1
1
  = Message Router
2
2
 
3
+ {<img src="https://travis-ci.org/polleverywhere/message_router.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/polleverywhere/message_router]
4
+ {<img src="https://codeclimate.com/github/polleverywhere/message_router/badges/gpa.svg" />}[https://codeclimate.com/github/polleverywhere/message_router]
5
+
3
6
  Message router is a DSL for routing and processing simple messages, like SMS messages or Tweets.
4
7
 
5
8
  == Installation
@@ -12,30 +15,30 @@ See rdoc for MessageRouter::Router.build (lib/message_router/router.rb) for exam
12
15
 
13
16
  And now some irb action.
14
17
 
15
- 1.8.7 :001 > class HelloRouter < MessageRouter::Router
16
- 1.8.7 :002?> match /hi/ do
17
- 1.8.7 :003 > puts "Hi there. You sent me: #{env.inspect}"
18
- 1.8.7 :004?> true # puts returns nil, and that would fail the matcher
19
- 1.8.7 :005?> end
20
- 1.8.7 :006?> end
21
- => [[/hi/, #<Proc:0x00000000026963b8@(irb):2>]]
22
- 1.8.7 :007 > HelloRouter.new.call({'body' => 'can you say hi to me?'})
23
- Hi there. You sent me: {'body'=>"can you say hi to me?"}
24
- => true
25
- 1.8.7 :008 > class MainRouter < MessageRouter::Router
26
- 1.8.7 :009?> match({'to' => 'greeter'}, HelloRouter.new)
27
- 1.8.7 :010?> match(true) do
28
- 1.8.7 :011 > puts "WTF? I don't know how to do that!"
29
- 1.8.7 :012?> true # puts returns nil, and that would fail the matcher
30
- 1.8.7 :013?> end
31
- 1.8.7 :014?> end
32
- => [[{:to=>"greeter"}, #<HelloRouter:0x25fef90 @rules=[[#<Proc:0x000000000266b2d0@/home/paul/sc/pe/message_router/lib/message_router/router.rb:165>, #<Proc:0x00000000026963b8@(irb):2>]]>], [true, #<Proc:0x00000000025ff580@(irb):10>]]
33
- 1.8.7 :015 > MainRouter.new.call({'body' => 'can you say hi to me?'})
34
- WTF? I don't know how to do that!
35
- => true
36
- 1.8.7 :016 > MainRouter.new.call({'body' => 'can you say hi to me?', 'to' => 'greeter'})
37
- Hi there. You sent me: {'body'=>"can you say hi to me?", 'to'=>"greeter"}
38
- => true
18
+ class HelloRouter < MessageRouter::Router
19
+ match /hi/ do
20
+ puts "Hi there. You sent me: #{env.inspect}"
21
+ true # puts returns nil, and that would fail the matcher
22
+ end
23
+ end
24
+ # => [[/hi/, #<Proc:0x00000000026963b8@(irb):2>]]
25
+ HelloRouter.call({'body' => 'can you say hi to me?'})
26
+ # Hi there. You sent me: {'body'=>"can you say hi to me?"}
27
+ # => true
28
+ class MainRouter < MessageRouter::Router
29
+ match({'to' => 'greeter'}, HelloRouter)
30
+ match(true) do
31
+ puts "WTF? I don't know how to do that!"
32
+ true # puts returns nil, and that would fail the matcher
33
+ end
34
+ end
35
+ # => [[{"to"=>"greeter"}, HelloRouter], [true, #<Proc:0x007f98c39e5b70@(irb):13>]]
36
+ MainRouter.call({'body' => 'can you say hi to me?'})
37
+ # WTF? I don't know how to do that!
38
+ # => true
39
+ MainRouter.call({'body' => 'can you say hi to me?', 'to' => 'greeter'})
40
+ # Hi there. You sent me: {'body'=>"can you say hi to me?", 'to'=>"greeter"}
41
+ # => true
39
42
 
40
43
 
41
44
  == TODO
@@ -57,7 +60,7 @@ Add tests to ensure that instance variables can be shared between initializers a
57
60
  @sender.puts 'something'
58
61
  end
59
62
  end
60
- MyRouter.new(:sender => STDOUT).call({}) # prints out 'something' to standard out.
63
+ MyRouter(:sender => STDOUT).call({}) # prints out 'something' to standard out.
61
64
 
62
65
  Pass Regexp captures on to the proc when there is a match. Examples:
63
66
  match /some (cool|awesome) thing/ do |match|
@@ -106,17 +109,17 @@ Make helper methods defined (or included) in parent routers available in sub rou
106
109
  Pass around copies of the env Hash instead of modifying the existing Hash in place.
107
110
  * This _might_ help with multi-threading
108
111
  * Perhaps a parent router wants to delegate to 2 sub-routers which are independent of each other. The current implementation has a shared env hash, so I couldn't use multi-threading, (though forking could work). I would have to trust the user to call #dup on at least one of the env hashes. With this new way, it is safe by default.
109
- * Convention would be for the 'should_i' Procs to return a copy of the env hashes, either modified or not, depending on their needs.
112
+ * Convention would be for the 'condition' Procs to return a copy of the env hashes, either modified or not, depending on their needs.
110
113
  * They would still return nil or false if they don't match.
111
114
  * We could also require (by convention only) that sub-routers also return a copy of the env hash (if they succeed) so this (optionally modified) env hash can be used for further routing.
112
115
  * This would give the original router access to both the modified env hash and the original env hash.
113
116
 
114
- Find a way to allow user-defined 'do_this' procs/blocks to not have to return a true value to be considered to have matched. We still need a way to know if a sub-router matched or not. This _may_require that the code treat sub-routers and user-defined 'do_this' procs/blocks differently, which could get awkward.
117
+ Find a way to allow user-defined 'action' procs/blocks to not have to return a true value to be considered to have matched. We still need a way to know if a sub-router matched or not. This _may_require that the code treat sub-routers and user-defined 'action' procs/blocks differently, which could get awkward.
115
118
 
116
119
  Allow routers to accept an optional logger. Depending on the log level, print out info such as:
117
120
  * When a matcher is registered
118
121
  * Each time a matcher is evaluated, including what the return value was.
119
- * Each time a 'do_this' block is evaluated, including what the return value was.
122
+ * Each time a 'action' block is evaluated, including what the return value was.
120
123
  Each time we write to the log include the following (depending on the log level):
121
124
  * The value of the env hash
122
125
  * The name of the class (so we can tell which subclass we are in)
@@ -132,21 +135,21 @@ Consider having a class called Run nested within the router's namespace. Instead
132
135
  end
133
136
  Run#run might look something like:
134
137
  def run
135
- router.rules.detect do |should_i, do_this|
136
- should_i = if should_i.kind_of?(Proc)
137
- self.instance_eval &should_i
138
+ router.rules.detect do |condition, action|
139
+ condition = if condition.kind_of?(Proc)
140
+ self.instance_eval &condition
138
141
  else
139
- should_i.call env
142
+ condition.call env
140
143
  end
141
144
 
142
- if should_i
143
- do_this = if do_this.kind_of?(Proc)
144
- self.instance_eval &do_this
145
+ if condition
146
+ action = if action.kind_of?(Proc)
147
+ self.instance_eval &action
145
148
  else
146
- do_this.call env
149
+ action.call env
147
150
  end
148
151
 
149
- return do_this if do_this
152
+ return action if action
150
153
  end
151
154
  end
152
155
  end
@@ -8,11 +8,11 @@ class MessageRouter
8
8
  #
9
9
  # prerequisite :db_connected?
10
10
  #
11
- # match SomeOtherRouter.new
11
+ # match SomeOtherRouter
12
12
  # # `mount` is an alias of `match`
13
- # mount AnotherRouter.new
13
+ # mount AnotherRouter
14
14
  #
15
- # match(lamba { env['from'].nil? }) do
15
+ # match(lambda { env['from'].nil? }) do
16
16
  # Logger.error "Can't reply when when don't know who a message is from: #{env.inspect}"
17
17
  # end
18
18
  #
@@ -40,13 +40,13 @@ class MessageRouter
40
40
  # send_reply "Sorry, you are trying to use a deprecated short code. Please try again.", env
41
41
  # end
42
42
  #
43
- # match :user_name => PriorityUsernameRouter.new
44
- # match :user_name, OldStyleUsernameRouter.new
43
+ # match :user_name => PriorityUsernameRouter
44
+ # match :user_name, OldStyleUsernameRouter
45
45
  # match :user_name do
46
46
  # send_reply "I found you! Your name is #{user_name}.", env
47
47
  # end
48
48
  #
49
- # match %w(stop end quit), StopRouter.new
49
+ # match %w(stop end quit), StopRouter
50
50
  #
51
51
  # # Array elements don't need to be the same type
52
52
  # match [
@@ -54,7 +54,7 @@ class MessageRouter
54
54
  # {'to' => %w(12345 54321)},
55
55
  # {'RAILS_ENV' => 'test'},
56
56
  # 'test'
57
- # ], TestRouter.new
57
+ # ], TestRouter
58
58
  #
59
59
  # # Works inside a Hash too
60
60
  # match 'from' => ['12345', '54321', /111\d\d/] do
@@ -80,7 +80,7 @@ class MessageRouter
80
80
  # end
81
81
  # end
82
82
  #
83
- # router = MyApp::Router::Application.new
83
+ # router = MyApp::Router::Application
84
84
  # router.call({}) # Logs an error about not knowing who the message is from
85
85
  # router.call({'from' => 'mr-smith', 'body' => 'ping'}) # Sends a 'pong' reply
86
86
  # router.call({'from' => 'mr-smith', 'to' => 12345}) # Sends a deprecation warning reply
@@ -149,28 +149,31 @@ class MessageRouter
149
149
  when 0
150
150
  raise ArgumentError, "You must provide either a block or an argument which responds to call."
151
151
  when 1
152
- if args[0].respond_to?(:call)
153
- should_i = true
154
- do_this = args[0]
152
+ if args[0].respond_to?(:env)
153
+ condition = true
154
+ action = args[0]
155
+ elsif args[0].respond_to?(:call)
156
+ condition = true
157
+ action = args[0]
155
158
  elsif args[0].kind_of?(Hash) && args[0].values.size == 1 && args[0].values[0].respond_to?(:call)
156
159
  # Syntactical suger to make:
157
- # match :cool? => OnlyForCoolPeopleRouter.new
160
+ # match :cool? => OnlyForCoolPeopleRouter
158
161
  # work just like:
159
- # match :cool?, OnlyForCoolPeopleRouter.new
160
- should_i = args[0].keys[0]
161
- do_this = args[0].values[0]
162
+ # match :cool?, OnlyForCoolPeopleRouter
163
+ condition = args[0].keys[0]
164
+ action = args[0].values[0]
162
165
  else
163
166
  raise ArgumentError, "You must provide either a block or a 2nd argument which responds to call."
164
167
  end
165
168
  when 2
166
- should_i, do_this = args
167
- raise ArgumentError, "The 2nd argument must respond to call." unless do_this.respond_to?(:call)
169
+ condition, action = args
170
+ raise ArgumentError, "The 2nd argument must respond to call." unless action.respond_to?(:call)
168
171
  else
169
172
  raise ArgumentError, "Too many arguments. Note: you may not provide a block when a 2nd argument has been provided."
170
173
  end
171
174
 
172
175
  # Save the arguments for later.
173
- rules << [should_i, do_this]
176
+ rules << [condition, action]
174
177
  end
175
178
  alias :mount :match
176
179
 
@@ -193,13 +196,34 @@ class MessageRouter
193
196
  def prerequisites
194
197
  @prerequisites ||= []
195
198
  end
199
+
200
+ # Kicks off the router. 'env' is a Hash. The keys are up to the user;
201
+ # however, the default key (used when a matcher is just a String or Regexp)
202
+ # is 'body'. If you don't specify this key, then String and Regexp matchers
203
+ # will always be false.
204
+ # Returns a new instance of this class, that gets run before being returned
205
+ # A rule "matches" if its condition return true and the action does not
206
+ # explicitly call not_matched. For example:
207
+ # match(true) { }
208
+ # matches. However:
209
+ # match(true) { not_matched }
210
+ # does not count as a match. This allows us to mount sub-routers and
211
+ # continue trying other rules if those subrouters fail to match something.
212
+ def call(env)
213
+ new(env).run
214
+ end
196
215
  end
197
216
 
198
217
 
199
218
  # This method initializes all the rules stored at the class level. When you
200
219
  # create your subclass, if you want to add your own initializer, it is very
201
220
  # important to call `super` or none of your rules will be matched.
202
- def initialize
221
+ def initialize(env) #:nodoc:
222
+ @env = env.dup
223
+ # a parent router may be assuming a successful match
224
+ # but this subrouter may not, so we explicitly set it to not matched
225
+ # on creation
226
+ not_matched
203
227
  @rules = []
204
228
  # Actually create the rules so that the procs we create are in the
205
229
  # context of an instance of this object. This is most important when the
@@ -209,100 +233,96 @@ class MessageRouter
209
233
  self.class.rules.each {|rule| match *rule }
210
234
 
211
235
  @prerequisites = []
212
- self.class.prerequisites.each {|prerequisite| @prerequisites << normalize_match_params(prerequisite) }
236
+ self.class.prerequisites.each do |prerequisite|
237
+ @prerequisites << normalize_match_params(prerequisite)
238
+ end
213
239
  end
214
240
 
215
- # Kicks off the router. 'env' is a Hash. The keys are up to the user;
216
- # however, the default key (used when a matcher is just a String or Regexp)
217
- # is 'body'. If you don't specify this key, then String and Regexp matchers
218
- # will always be false.
219
- # Returns nil if no rules match
220
- # Returns true if a rule matches
221
- # A rule "matches" if both its procs return true. For example:
222
- # match(true) { true }
223
- # matches. However:
224
- # match(true) { false }
225
- # does not count as a match. This allows us to mount sub-routers and
226
- # continue trying other rules if those subrouters fail to match something.
227
- # However, this does mean you need to be careful when writing the 2nd
228
- # argument to #match. If you return nil or false, the router will keep
229
- # looking for another match.
230
- def call(env)
231
- # I'm pretty sure this is NOT thread safe. Having two threads use the
232
- # same router at the same time will almost certainly give you VERY weird
233
- # and incorrect results. We may want to introduce a RouterRun object to
234
- # encapsulate one invocation of this #call method.
235
- @env = env
236
-
241
+ def run #:nodoc:
237
242
  # All prerequisites must return true in order to continue.
238
- return false unless @prerequisites.all? do |should_i|
239
- if should_i.kind_of?(Proc)
240
- self.instance_eval &should_i
241
- else
242
- should_i.call @env
243
- end
243
+ return self unless @prerequisites.all? do |condition|
244
+ self.instance_eval &condition
244
245
  end
245
246
 
246
- @rules.detect do |should_i, do_this|
247
- should_i = if should_i.kind_of?(Proc)
248
- self.instance_eval &should_i
249
- else
250
- should_i.call @env
247
+ @rules.detect do |condition, action|
248
+ if self.instance_eval &condition
249
+ matched
250
+ r = self.instance_eval &action
251
+ @env = r.respond_to?(:env) ? r.env : r
252
+ return self if matched?
251
253
  end
254
+ end
252
255
 
253
- if should_i
254
- do_this = if do_this.kind_of?(Proc)
255
- self.instance_eval &do_this
256
- else
257
- do_this.call @env
258
- end
256
+ self # always return router instance
257
+ end
259
258
 
260
- return true if do_this
261
- end
262
- end
263
- ensure
264
- @env = nil
259
+ def not_matched
260
+ env['_matched'] = false
261
+ end
262
+ def matched
263
+ env['_matched'] = true
264
+ end
265
+ def matched?
266
+ !!env['_matched']
265
267
  end
266
268
 
267
269
 
268
- private
269
270
  def env; @env; end
271
+ private
270
272
 
271
- def match(should_i, do_this)
272
- @rules << [normalize_match_params(should_i), do_this]
273
+ def match(condition, action)
274
+ @rules << [normalize_match_params(condition), normalize_action(action)]
275
+ end
276
+
277
+ def normalize_action(action)
278
+ if action.kind_of?(Proc) # This is true for blocks and lamdas too.
279
+ Proc.new do
280
+ self.instance_eval &action
281
+ env
282
+ end
283
+ else
284
+ Proc.new do
285
+ action.call(env)
286
+ end
287
+ end
273
288
  end
274
289
 
275
- def normalize_match_params(should_i=nil, &block)
276
- should_i ||= block if block
290
+ def normalize_match_params(condition=nil, &block)
291
+ condition ||= block if block
277
292
 
278
- case should_i
293
+ case condition
279
294
  when Regexp, String
280
- Proc.new { attr_matches? default_attribute, should_i }
295
+ Proc.new { attr_matches? default_attribute, condition }
281
296
 
282
297
  when TrueClass, FalseClass, NilClass
283
- Proc.new { should_i }
298
+ Proc.new { condition }
284
299
 
285
300
  when Symbol
286
301
  Proc.new do
287
- self.send should_i
302
+ self.send condition
288
303
  end
289
304
 
290
305
  when Array
291
- should_i = should_i.map {|x| normalize_match_params x}
306
+ condition = condition.map {|x| normalize_match_params x}
292
307
  Proc.new do
293
- should_i.any? { |x| x.call env }
308
+ condition.any? { |x| x.call env }
294
309
  end
295
310
 
296
311
  when Hash
297
312
  Proc.new do
298
- should_i.all? do |key, val|
313
+ condition.all? do |key, val|
299
314
  attr_matches? env[key], val
300
315
  end
301
316
  end
302
317
 
318
+ when Proc
319
+ condition
320
+
303
321
  else
304
322
  # Assume it already responds to #call.
305
- should_i
323
+ Proc.new do
324
+ condition.call env
325
+ end
306
326
  end
307
327
  end
308
328
 
@@ -1,3 +1,3 @@
1
1
  class MessageRouter
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -5,8 +5,8 @@ require "message_router/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "message_router"
7
7
  s.version = MessageRouter::VERSION
8
- s.authors = ["Brad Gessler", "Paul Cortens"]
9
- s.email = ["brad@bradgessler.com", "paul@thoughtless.ca"]
8
+ s.authors = ["Brad Gessler", "Paul Cortens", "Christopher Bertels"]
9
+ s.email = ["brad@bradgessler.com", "paul@thoughtless.ca", "bakkdoor@flasht.de"]
10
10
  s.homepage = ""
11
11
  s.summary = %q{Route messages}
12
12
  s.description = %q{a DSL for routing SMS, Twitter, and other short message formats.}
@@ -5,11 +5,6 @@ describe MessageRouter::Router do
5
5
 
6
6
  describe 'defining matchers' do
7
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
12
-
13
8
  let :env do
14
9
  {
15
10
  'body' => 'hello world',
@@ -19,10 +14,10 @@ describe MessageRouter::Router do
19
14
  end
20
15
 
21
16
  # 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
17
+ # thing_to_match can change within a test.
18
+ def router(thing_to_match)
24
19
  Class.new MessageRouter::Router do
25
- match($thing_to_match) { $did_it_run = true }
20
+ match(thing_to_match) { env['did_it_run'] = true }
26
21
 
27
22
  # Using these methods also proves that the message is optionally
28
23
  # passed to helper methods.
@@ -32,20 +27,16 @@ describe MessageRouter::Router do
32
27
  def always_false
33
28
  false
34
29
  end
35
- end.new
30
+ end
36
31
  end
37
32
 
38
33
  let :the_test do
39
34
  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
35
+ r = router(opts[:true]).call(env.dup)
36
+ expect(r.env['did_it_run']).to eq true
44
37
 
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
+ r = router(opts[:false]).call(env.dup)
39
+ expect(r.env['did_it_run']).to eq nil
49
40
  end
50
41
  end
51
42
 
@@ -82,27 +73,27 @@ describe MessageRouter::Router do
82
73
  def default_attribute
83
74
  env['tacos']
84
75
  end
85
- end.new
76
+ end
86
77
  end
87
78
 
88
79
  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'
80
+ r = router.call({ 'tacos' => 'cheese please' })
81
+ expect(r.matched?).to be_truthy
82
+ expect(r.env['result']).to eq 'i found cheese'
92
83
  end
93
84
  it "does not match strings against the 'body' attribute" do
94
- env = { 'body' => 'cheese please' }
95
- router.call(env).should be_nil
85
+ r = router.call({ 'body' => 'cheese please' })
86
+ expect(r.matched?).to be_falsey
96
87
  end
97
88
 
98
89
  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'
90
+ r = router.call({ 'tacos' => 'i like beans a lot' })
91
+ expect(r.matched?).to be_truthy
92
+ expect(r.env['result']).to eq 'magical fruit'
102
93
  end
103
94
  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
95
+ r = router.call({ 'body' => 'i like beans a lot' })
96
+ expect(r.matched?).to be_falsey
106
97
  end
107
98
  end
108
99
 
@@ -115,31 +106,18 @@ describe MessageRouter::Router do
115
106
  end
116
107
 
117
108
  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
126
-
127
- router.call({})
128
- $run_count.should == 1
129
- end
130
-
131
- it "returns nil if the 'do_this' block returns nil" do
132
- $run_count = 0
109
+ it "doesn't run the 'action' block multiple times if there are multiple matches" do
110
+ run = double
111
+ expect(run).to receive(:count).once
133
112
  router = Class.new(MessageRouter::Router) do
134
113
  match [true, true] do
135
- $run_count += 1
136
- nil # Return nil to ensure this matcher failed.
114
+ run.count
115
+ not_matched
137
116
  end
138
- end.new
139
-
140
- router.call({}).should == nil
117
+ end
118
+ r = router.call({})
119
+ expect(r.matched?).to be_falsey
141
120
  end
142
-
143
121
  end
144
122
 
145
123
  describe 'matching a hash' do
@@ -181,10 +159,8 @@ describe MessageRouter::Router do
181
159
  end
182
160
 
183
161
  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
162
+ r = router({'i dont exist' => /.*/}).call(env)
163
+ expect(r.env['did_it_run']).to eq nil
188
164
  end
189
165
  end
190
166
  end
@@ -194,34 +170,34 @@ describe MessageRouter::Router do
194
170
  env = {}
195
171
  router = Class.new MessageRouter::Router do
196
172
  match(true, Proc.new { env['did_it_run'] = true })
197
- end.new
173
+ end
198
174
  router.call env
199
- env['did_it_run'].should be_true
175
+ expect(env['did_it_run']).to be_truthy
200
176
  end
201
177
 
202
178
  it 'accepts a block' do
203
179
  env = {}
204
180
  router = Class.new MessageRouter::Router do
205
181
  match(true) { env['did_it_run'] = true }
206
- end.new
182
+ end
207
183
  router.call env
208
- env['did_it_run'].should be_true
184
+ expect(env['did_it_run']).to be_truthy
209
185
  end
210
186
 
211
187
  it 'raises an execption when both a Proc and a block are given' do
212
- lambda {
188
+ expect {
213
189
  router = Class.new MessageRouter::Router do
214
190
  match(true, Proc.new { env['did_it_run'] = true }) { env['did_it_run'] = true }
215
- end.new
216
- }.should raise_error(ArgumentError)
191
+ end
192
+ }.to raise_error(ArgumentError)
217
193
  end
218
194
 
219
195
  it 'raises an execption when neither a Proc nor a block are given' do
220
- lambda {
196
+ expect {
221
197
  router = Class.new MessageRouter::Router do
222
198
  match true
223
- end.new
224
- }.should raise_error(ArgumentError)
199
+ end
200
+ }.to raise_error(ArgumentError)
225
201
  end
226
202
  end
227
203
 
@@ -229,18 +205,18 @@ describe MessageRouter::Router do
229
205
  env = {}
230
206
  router = Class.new MessageRouter::Router do
231
207
  match { env['did_it_run'] = true }
232
- end.new
208
+ end
233
209
  router.call env
234
- env['did_it_run'].should be_true
210
+ expect(env['did_it_run']).to be_truthy
235
211
  end
236
212
 
237
213
  it 'defaults the 1st argument to true if only a Proc is given' do
238
214
  env = {}
239
215
  router = Class.new MessageRouter::Router do
240
216
  match(Proc.new { env['did_it_run'] = true })
241
- end.new
217
+ end
242
218
  router.call env
243
- env['did_it_run'].should be_true
219
+ expect(env['did_it_run']).to be_truthy
244
220
  end
245
221
 
246
222
  it 'accepts a Hash with a symbol as its only key and a Proc as its only value' do
@@ -248,41 +224,41 @@ describe MessageRouter::Router do
248
224
  router = Class.new MessageRouter::Router do
249
225
  match :true_method => (Proc.new { env['did_it_run'] = true })
250
226
  def true_method; true; end
251
- end.new
227
+ end
252
228
  router.call env
253
- env['did_it_run'].should be_true
229
+ expect(env['did_it_run']).to be_truthy
254
230
  end
255
231
 
256
232
  it 'raises an execption when no arguments and no block is given' do
257
- lambda {
233
+ expect {
258
234
  router = Class.new MessageRouter::Router do
259
235
  match
260
- end.new
261
- }.should raise_error(ArgumentError)
236
+ end
237
+ }.to raise_error(ArgumentError)
262
238
  end
263
239
  end
264
240
 
265
241
 
266
242
  describe "#call" do
267
- it "returns nil with no rules" do
268
- r = MessageRouter::Router.new
269
- r.call({}).should be_nil
243
+ it "does not match with no rules" do
244
+ router = MessageRouter::Router.call({})
245
+ expect(router.matched?).to be_falsey
270
246
  end
271
247
 
272
248
  context 'a rule matches' do
273
249
  subject do
274
250
  Class.new MessageRouter::Router do
275
251
  match(true) { env[:did_it_run] = true }
276
- end.new
252
+ end
277
253
  end
278
254
 
279
255
  it "returns true" do
280
- subject.call({}).should be_true
256
+ expect(subject.call({})).to be_truthy
281
257
  end
282
258
 
283
259
  it "calls the matcher's code" do
284
- subject.call(env = {})
285
- env[:did_it_run].should be_true
260
+ r = subject.call(env = {})
261
+ expect(r.env[:did_it_run]).to be_truthy
286
262
  end
287
263
  end
288
264
 
@@ -292,16 +268,16 @@ describe MessageRouter::Router do
292
268
  prerequisite :true_method
293
269
  match(true) { env[:did_it_run] = true }
294
270
  def true_method; true; end
295
- end.new
271
+ end
296
272
  end
297
273
 
298
- it "returns true" do
299
- subject.call({}).should be_true
274
+ it "matches" do
275
+ expect(subject.call({}).matched?).to be_truthy
300
276
  end
301
277
 
302
278
  it "calls the matcher's code" do
303
- subject.call(env = {})
304
- env[:did_it_run].should be_true
279
+ r = subject.call(env = {})
280
+ expect(r.env[:did_it_run]).to be_truthy
305
281
  end
306
282
  end
307
283
 
@@ -311,112 +287,126 @@ describe MessageRouter::Router do
311
287
  prerequisite :false_method
312
288
  match(true) { env[:did_it_run] = true }
313
289
  def false_method; false; end
314
- end.new
290
+ end
315
291
  end
316
292
 
317
- it "returns false" do
318
- subject.call({}).should be_false
293
+ it "doesn't match" do
294
+ expect(subject.call({}).matched?).to be_falsey
319
295
  end
320
296
 
321
297
  it "doesn't calls the matcher's code" do
322
298
  subject.call(env = {})
323
- env[:did_it_run].should_not be_true
299
+ expect(env[:did_it_run]).to_not be_truthy
324
300
  end
325
301
  end
326
302
 
327
- describe 'nested routers' do
328
- def main_router
303
+ describe 'mount routers' do
304
+ it "can delegate to other routers" do
305
+ sub_router = Class.new(MessageRouter::Router) do
306
+ match do
307
+ env['result'] = true
308
+ end
309
+ end
310
+
311
+ main_router = Class.new(MessageRouter::Router) do
312
+ mount sub_router
313
+ end
314
+
315
+ r = main_router.call({})
316
+ expect(r.env['result']).to eq true
317
+ end
318
+ end
319
+
320
+ describe "explicitly not matching" do
321
+ let(:router) do
329
322
  Class.new(MessageRouter::Router) do
330
- sub_router = Class.new(MessageRouter::Router) do
331
- match($inner_matcher) { $did_inner_run = true }
332
- end.new
323
+ match do
324
+ not_matched
325
+ end
326
+ end
327
+ end
333
328
 
334
- match $outer_matcher do
335
- $did_outer_run = true
336
- sub_router.call(env)
329
+ it "sets matched to false in env" do
330
+ r = router.call({})
331
+ expect(r.matched?).to be_falsey
332
+ end
333
+ end
334
+
335
+ describe "explicitly matching" do
336
+ let(:router) do
337
+ Class.new(MessageRouter::Router) do
338
+ match do
339
+ not_matched
337
340
  end
338
- end.new
341
+ match do
342
+ matched
343
+ end
344
+ end
339
345
  end
340
346
 
341
- before do
342
- $outer_matcher = $inner_matcher = $did_outer_run = $did_inner_run = nil
347
+ it "sets matched to true in env" do
348
+ r = router.call({})
349
+ expect(r.matched?).to be_truthy
343
350
  end
351
+ end
344
352
 
345
- it 'runs both when both match' do
346
- $outer_matcher = $inner_matcher = true
353
+ describe 'nested routers' do
354
+ def main_router(matcher_opts = {})
355
+ Class.new(MessageRouter::Router) do
356
+ sub_router = Class.new(MessageRouter::Router) do
357
+ match { not_matched; env['did_outer_run'] = true }
358
+ match(matcher_opts[:inner]) { env['did_inner_run'] = true }
359
+ end
347
360
 
348
- main_router.call({}).should be_true
349
- $did_outer_run.should be_true
350
- $did_inner_run.should be_true
361
+ match matcher_opts[:outer] => sub_router
362
+ end
351
363
  end
352
364
 
353
- it "runs outer only when outer matches and inner doesn't" do
354
- $outer_matcher = true
355
- $inner_matcher = false
365
+ it 'runs both when both match' do
366
+ r = main_router(:outer => true, :inner => true).call({})
367
+ expect(r.env['did_outer_run']).to be_truthy
368
+ expect(r.env['did_inner_run']).to be_truthy
369
+ end
356
370
 
357
- main_router.call({}).should be_nil
358
- $did_outer_run.should be_true
359
- $did_inner_run.should be_nil
371
+ it "runs outer only when outer matches and inner doesn't" do
372
+ r = main_router(:outer => true, :inner => false).call({})
373
+ expect(r.env['did_outer_run']).to be_truthy
374
+ expect(r.env['did_inner_run']).to be_nil
360
375
  end
361
376
 
362
377
  it "runs neither when inner matches and outer doesn't" do
363
- $outer_matcher = false
364
- $inner_matcher = true
365
-
366
- main_router.call({}).should be_nil
367
- $did_outer_run.should be_nil
368
- $did_inner_run.should be_nil
378
+ r = main_router(:outer => false, :inner => true).call({})
379
+ expect(r.env['did_outer_run']).to be_nil
380
+ expect(r.env['did_inner_run']).to be_nil
369
381
  end
370
382
 
371
383
  context 'multiple inner matchers' do
372
- before do
373
- $outer_matcher_1 = $outer_matcher_2 = $inner_matcher_1 = $inner_matcher_2 = $did_outer_run_1 = $did_outer_run_2 = $did_inner_run_1 = $did_inner_run_2 = nil
374
- end
375
-
376
- def main_router
384
+ def main_router(inner_matcher_1)
377
385
  Class.new MessageRouter::Router do
378
386
  # Define them
379
387
  sub_router_1 = Class.new MessageRouter::Router do
380
- match($inner_matcher_1) { $did_inner_run_1 = true }
381
- end.new
388
+ match(inner_matcher_1) { env['did_inner_run_1'] = true }
389
+ end
382
390
  sub_router_2 = Class.new MessageRouter::Router do
383
- match($inner_matcher_2) { $did_inner_run_2 = true }
384
- end.new
385
-
386
- # 'mount' them
387
- match $outer_matcher_1 do
388
- $did_outer_run_1 = true
389
- sub_router_1.call(env)
391
+ match(true) { env['did_inner_run_2'] = true }
390
392
  end
391
393
 
392
- match $outer_matcher_2 do
393
- $did_outer_run_2 = true
394
- sub_router_2.call(env)
395
- end
396
- end.new
394
+ mount sub_router_1
395
+ mount sub_router_2
396
+ end
397
397
  end
398
398
 
399
399
  it "runs only 1st outer and 1st inner when all match" do
400
- $outer_matcher_1 = $outer_matcher_2 = $inner_matcher_1 = $inner_matcher_2 = true
401
-
402
- main_router.call({}).should be_true
403
- $did_outer_run_1.should be_true
404
- $did_outer_run_2.should be_nil
405
- $did_inner_run_1.should be_true
406
- $did_inner_run_2.should be_nil
400
+ r = main_router(true).call({})
401
+ expect(r.env['did_inner_run_1']).to eq true
402
+ expect(r.env['did_inner_run_2']).to eq nil
407
403
  end
408
404
 
409
405
  it "runs both outers, and 2nd inner when all but 1st inner match" do
410
- $outer_matcher_1 = $outer_matcher_2 = $inner_matcher_2 = true
411
- $inner_matcher_1 = false
412
-
413
- main_router.call({}).should be_true
414
- $did_outer_run_1.should be_true
415
- $did_outer_run_2.should be_true
416
- $did_inner_run_1.should be_nil
417
- $did_inner_run_2.should be_true
406
+ r = main_router(false).call({})
407
+ expect(r.env['did_inner_run_1']).to be_nil
408
+ expect(r.env['did_inner_run_2']).to be_truthy
418
409
  end
419
-
420
410
  end
421
411
  end
422
412
 
@@ -437,7 +427,7 @@ describe MessageRouter::Router do
437
427
  Class.new MessageRouter::Router do
438
428
  include MyTestHelper
439
429
  match :lookup_human_name do
440
- $is_john = env['human_name'] == 'John'
430
+ env['is_john'] = env['human_name'] == 'John'
441
431
  end
442
432
 
443
433
  match 'run_a' => 'block' do
@@ -448,7 +438,7 @@ describe MessageRouter::Router do
448
438
  env['id'] = 2
449
439
  env['the_name'] = lookup_human_name
450
440
  end)
451
- match({'run_a' => 'lambda'}, lambda do
441
+ match({'run_a' => 'lambda'}, lambda do |args|
452
442
  env['id'] = 2
453
443
  env['the_name'] = lookup_human_name
454
444
  end)
@@ -459,34 +449,53 @@ describe MessageRouter::Router do
459
449
  lookup_human_name
460
450
  end
461
451
  ) { true }
462
- end.new
452
+ end
463
453
  end
464
454
 
465
455
  it 'can access/modify the env via #env' do
466
- env = {'id' => 1}
467
- router.call(env).should be_true
468
- $is_john.should be_true # Prove the inner matcher can see the new value
469
- env['human_name'].should == 'John' # Prove we can get at the value after the router has finished.
470
- end
471
-
472
- it '#env is reset after #call has finished' do
473
- router.call({'id' => 1}).should be_true
474
- router.send(:env).should be_nil
456
+ r = router.call({'id' => 1})
457
+ expect(r.matched?).to be_truthy
458
+ expect(r.env['is_john']).to be_truthy # Prove the inner matcher can see the new value
459
+ expect(r.env['human_name']).to eq 'John' # Prove we can get at the value after the router has finished.
475
460
  end
476
461
 
477
462
  %w(block proc lambda).each do |type|
478
463
  it "can be accessed from a #{type} that is the 2nd argument" do
479
- env = {'run_a' => type}
480
- router.call(env).should be_true
481
- env['the_name'].should == 'Jim'
464
+ r = router.call({'run_a' => type})
465
+ expect(r.matched?).to be_truthy
466
+ expect(r.env['the_name']).to eq 'Jim'
482
467
  end
483
468
  end
484
469
 
485
470
  %w(proc lambda).each do |type|
486
471
  it "can be accessed from a #{type} that is the 1st argument" do
487
- env = {'match_with' => type}
488
- router.call(env).should be_true
489
- env['human_name'].should == 'Jules'
472
+ r = router.call({'match_with' => type})
473
+ expect(r.matched?).to be_truthy
474
+ expect(r.env['human_name']).to eq 'Jules'
475
+ end
476
+ end
477
+
478
+ describe "instance variables" do
479
+ let :router do
480
+ Class.new MessageRouter::Router do
481
+ prerequisite :helper_method
482
+
483
+ match do
484
+ env['result'] = @helper_method
485
+ end
486
+
487
+ private
488
+ def helper_method
489
+ @helper_method ||= 0
490
+ @helper_method += 1
491
+ end
492
+ end
493
+ end
494
+
495
+ it "doesn't leak state to a 2nd run" do
496
+ router.call({})
497
+ r = router.call({})
498
+ expect(r.env['result']).to eq 1
490
499
  end
491
500
  end
492
501
  end
metadata CHANGED
@@ -1,37 +1,29 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: message_router
3
- version: !ruby/object:Gem::Version
4
- hash: 29
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Brad Gessler
14
8
  - Paul Cortens
9
+ - Christopher Bertels
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2012-09-10 00:00:00 Z
13
+ date: 2014-10-21 00:00:00.000000000 Z
20
14
  dependencies: []
21
-
22
15
  description: a DSL for routing SMS, Twitter, and other short message formats.
23
- email:
16
+ email:
24
17
  - brad@bradgessler.com
25
18
  - paul@thoughtless.ca
19
+ - bakkdoor@flasht.de
26
20
  executables: []
27
-
28
21
  extensions: []
29
-
30
22
  extra_rdoc_files: []
31
-
32
- files:
33
- - .gitignore
34
- - .rvmrc
23
+ files:
24
+ - ".gitignore"
25
+ - ".ruby-version"
26
+ - ".travis.yml"
35
27
  - Gemfile
36
28
  - Gemfile.lock
37
29
  - Guardfile
@@ -45,38 +37,30 @@ files:
45
37
  - spec/message_router_spec.rb
46
38
  - spec/spec.opts
47
39
  - spec/spec_helper.rb
48
- homepage: ""
40
+ homepage: ''
49
41
  licenses: []
50
-
42
+ metadata: {}
51
43
  post_install_message:
52
44
  rdoc_options: []
53
-
54
- require_paths:
45
+ require_paths:
55
46
  - lib
56
- required_ruby_version: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
59
49
  - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
65
- required_rubygems_version: !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
68
54
  - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
74
57
  requirements: []
75
-
76
58
  rubyforge_project: message_router
77
- rubygems_version: 1.8.22
59
+ rubygems_version: 2.2.2
78
60
  signing_key:
79
- specification_version: 3
61
+ specification_version: 4
80
62
  summary: Route messages
81
- test_files: []
82
-
63
+ test_files:
64
+ - spec/message_router_spec.rb
65
+ - spec/spec.opts
66
+ - spec/spec_helper.rb
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm use --install ree