message_router 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +12 -20
- data/Guardfile +1 -1
- data/README.rdoc +8 -8
- data/Rakefile +14 -23
- data/lib/message_router.rb +17 -6
- data/lib/message_router/matcher.rb +4 -4
- data/lib/message_router/version.rb +1 -1
- data/spec/message_router_spec.rb +31 -18
- metadata +4 -5
- data/.document +0 -5
data/Gemfile.lock
CHANGED
@@ -1,34 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
message_router (0.0.
|
4
|
+
message_router (0.0.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
-
configuration (1.2.0)
|
10
9
|
diff-lcs (1.1.2)
|
11
10
|
growl (1.0.3)
|
12
|
-
guard (0.
|
13
|
-
open_gem (~> 1.4.2)
|
11
|
+
guard (0.5.1)
|
14
12
|
thor (~> 0.14.6)
|
15
|
-
guard-rspec (0.
|
16
|
-
guard (>= 0.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
rspec (2.5.0)
|
25
|
-
rspec-core (~> 2.5.0)
|
26
|
-
rspec-expectations (~> 2.5.0)
|
27
|
-
rspec-mocks (~> 2.5.0)
|
28
|
-
rspec-core (2.5.1)
|
29
|
-
rspec-expectations (2.5.0)
|
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)
|
30
22
|
diff-lcs (~> 1.1.2)
|
31
|
-
rspec-mocks (2.
|
23
|
+
rspec-mocks (2.6.0)
|
32
24
|
thor (0.14.6)
|
33
25
|
|
34
26
|
PLATFORMS
|
data/Guardfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# A sample Guardfile
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
3
3
|
|
4
|
-
guard 'rspec', :version => 2, :notification => true do
|
4
|
+
guard 'rspec', :version => 2, :cli => '--colour', :notification => true do
|
5
5
|
watch(%r{^spec/.+_spec\.rb})
|
6
6
|
watch(%r{^lib/(.+)\.rb}) { |m| "spec/message_router_spec.rb" }
|
7
7
|
watch(/^spec\/spec_helper.rb/) { "spec" }
|
data/README.rdoc
CHANGED
@@ -44,14 +44,14 @@ This is a contrived example for a Twitter message router, but it gives you an id
|
|
44
44
|
|
45
45
|
And now some irb action.
|
46
46
|
|
47
|
-
>> TwitterRouter.new(
|
48
|
-
=> "pleased to meet you"
|
49
|
-
>> TwitterRouter.new(
|
50
|
-
=> "how do you do brad"
|
51
|
-
>> TwitterRouter.new(
|
52
|
-
=> "STOP SHOUTING WITH NUMBERS!"
|
53
|
-
>> TwitterRouter.new(
|
54
|
-
=> "STOP SHOUTING WITHOUT NUMBERS!"
|
47
|
+
>> TwitterRouter.new(:body => 'hi dude').dispatch
|
48
|
+
=> {:body => "pleased to meet you"}
|
49
|
+
>> TwitterRouter.new(:body => 'hi brad').dispatch
|
50
|
+
=> {:body => "how do you do brad"}
|
51
|
+
>> TwitterRouter.new(:body => 'HI BRAD 90').dispatch
|
52
|
+
=> {:body => "STOP SHOUTING WITH NUMBERS!"}
|
53
|
+
>> TwitterRouter.new(:body => 'HI BRAD').dispatch
|
54
|
+
=> {:body => "STOP SHOUTING WITHOUT NUMBERS!"}
|
55
55
|
|
56
56
|
== License
|
57
57
|
|
data/Rakefile
CHANGED
@@ -1,27 +1,18 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
# spec.spec_files = FileList['spec/**/*_spec.rb']
|
7
|
-
# end
|
4
|
+
desc 'Default: run specs.'
|
5
|
+
task :default => :spec
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
|
7
|
+
desc "Run specs"
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
10
|
+
# Put spec opts in a file named .rspec in root
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
22
|
-
|
23
|
-
# rdoc.rdoc_dir = 'rdoc'
|
24
|
-
# rdoc.title = "message_router #{version}"
|
25
|
-
# rdoc.rdoc_files.include('README*')
|
26
|
-
# rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
-
# end
|
13
|
+
desc "Generate code coverage"
|
14
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
15
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
16
|
+
t.rcov = true
|
17
|
+
t.rcov_opts = ['--exclude', 'spec']
|
18
|
+
end
|
data/lib/message_router.rb
CHANGED
@@ -27,20 +27,20 @@ class MessageRouter
|
|
27
27
|
routes.push proc
|
28
28
|
end
|
29
29
|
|
30
|
-
def dispatch(
|
31
|
-
new(
|
30
|
+
def dispatch(*args)
|
31
|
+
new(*args).dispatch
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
attr_accessor :message, :halted_value
|
36
36
|
|
37
|
-
def initialize(
|
38
|
-
@message =
|
37
|
+
def initialize(*args)
|
38
|
+
@message = normalize_arguments(*args)
|
39
39
|
end
|
40
40
|
|
41
|
-
def halt(val=nil)
|
41
|
+
def halt(val=nil, opts={})
|
42
42
|
@halted = true
|
43
|
-
@halted_value = val
|
43
|
+
@halted_value = normalize_arguments(val, opts)
|
44
44
|
end
|
45
45
|
|
46
46
|
def halted?
|
@@ -59,4 +59,15 @@ class MessageRouter
|
|
59
59
|
end
|
60
60
|
return nil # If nothing is matched, we get here and we should return a nil
|
61
61
|
end
|
62
|
+
|
63
|
+
def default_key
|
64
|
+
:body
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
# Make our router accept the first argument as the default message key, then optional keys last.
|
69
|
+
def normalize_arguments(message=nil, opts={})
|
70
|
+
message = opts.merge(:body => message) unless message.is_a? Hash and opts.empty?
|
71
|
+
message
|
72
|
+
end
|
62
73
|
end
|
@@ -25,11 +25,11 @@ class MessageRouter
|
|
25
25
|
|
26
26
|
def call(router)
|
27
27
|
if match = match(router.message)
|
28
|
-
router.instance_exec(*match[self.class.
|
28
|
+
router.instance_exec(*match[self.class.default_key], &block)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def self.
|
32
|
+
def self.default_key
|
33
33
|
:body
|
34
34
|
end
|
35
35
|
|
@@ -38,11 +38,11 @@ class MessageRouter
|
|
38
38
|
|
39
39
|
def normalize_params(*args)
|
40
40
|
if args.size == 2
|
41
|
-
args.last.merge(self.class.
|
41
|
+
args.last.merge(self.class.default_key => args.first)
|
42
42
|
elsif args.size == 1 and args.first.is_a?(Hash)
|
43
43
|
args.first
|
44
44
|
elsif args.size == 1
|
45
|
-
{ self.class.
|
45
|
+
{ self.class.default_key => args.first }
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
data/spec/message_router_spec.rb
CHANGED
@@ -30,14 +30,14 @@ describe MessageRouter::Matcher do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should default matcher param to :body" do
|
33
|
-
MessageRouter::Matcher.
|
33
|
+
MessageRouter::Matcher.default_key.should eql(:body)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
describe MessageRouter do
|
38
38
|
class CrazyTimesRouter < MessageRouter
|
39
39
|
match /^crazy$/ do
|
40
|
-
"factory blow out sales are awesome"
|
40
|
+
halt "factory blow out sales are awesome"
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -45,25 +45,25 @@ describe MessageRouter do
|
|
45
45
|
class TwitterRouter < MessageRouter
|
46
46
|
context :all_caps_with_numbers do |funny_word, high_def_resolution|
|
47
47
|
match /FUNNYWORD/i do
|
48
|
-
"#{funny_word}-#{high_def_resolution}"
|
48
|
+
halt "#{funny_word}-#{high_def_resolution}"
|
49
49
|
end
|
50
50
|
|
51
51
|
# All caps without numbers... but in a proc
|
52
52
|
context Proc.new{|r| r.message[:body] =~ /^[A-Z\s]+$/ } do
|
53
53
|
match /.+/ do
|
54
|
-
"STOP SHOUTING WITHOUT NUMBERS!"
|
54
|
+
halt "STOP SHOUTING WITHOUT NUMBERS!"
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
match /.+/ do
|
59
|
-
"STOP SHOUTING WITH NUMBERS!"
|
59
|
+
halt "STOP SHOUTING WITH NUMBERS!"
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
63
|
mount CrazyTimesRouter
|
64
64
|
|
65
65
|
match /hi dude/ do
|
66
|
-
"pleased to meet you"
|
66
|
+
halt "pleased to meet you"
|
67
67
|
end
|
68
68
|
|
69
69
|
match /hi halt (\w+)/ do |word|
|
@@ -75,11 +75,11 @@ describe MessageRouter do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
match /hi (\w+)/ do |name|
|
78
|
-
"how do you do #{name}"
|
78
|
+
halt "how do you do #{name}"
|
79
79
|
end
|
80
80
|
|
81
81
|
match /hola (\w+) (\w+)/, :from => 'bradgessler' do |first_name, last_name|
|
82
|
-
"hello #{first_name} #{last_name} in spanish"
|
82
|
+
halt "hello #{first_name} #{last_name} in spanish"
|
83
83
|
end
|
84
84
|
|
85
85
|
private
|
@@ -90,53 +90,66 @@ describe MessageRouter do
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
def dispatch(*args)
|
94
|
+
reply = TwitterRouter.dispatch(*args)
|
95
|
+
reply ? reply[:body] : nil
|
96
|
+
end
|
97
|
+
|
93
98
|
it "should return nil if there are no matches" do
|
94
|
-
|
99
|
+
dispatch("bums").should be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should have default key" do
|
103
|
+
TwitterRouter.new.default_key.should eql(:body)
|
95
104
|
end
|
96
105
|
|
97
106
|
context "mounted router" do
|
98
107
|
it "should process message" do
|
99
|
-
|
108
|
+
dispatch("crazy").should eql("factory blow out sales are awesome")
|
100
109
|
end
|
101
110
|
end
|
102
111
|
|
103
112
|
context "should halt" do
|
104
113
|
it "without value" do
|
105
|
-
|
114
|
+
dispatch("hi halt").should be_nil
|
106
115
|
end
|
107
116
|
|
108
117
|
it "with value" do
|
109
|
-
|
118
|
+
dispatch("hi halt narf").should eql("narf")
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
113
122
|
context "default matcher" do
|
114
123
|
it "should capture regexps" do
|
115
|
-
|
124
|
+
dispatch('hi dude').should eql('pleased to meet you')
|
116
125
|
end
|
117
126
|
|
118
127
|
it "should pass regexp captures through blocks" do
|
119
|
-
|
128
|
+
dispatch('hi brad').should eql("how do you do brad")
|
120
129
|
end
|
121
130
|
end
|
122
131
|
|
123
132
|
context "hash matcher" do
|
124
133
|
it "should capture with default matcher" do
|
125
|
-
|
134
|
+
dispatch('hola jeannette gessler', :from => 'bradgessler').should eql("hello jeannette gessler in spanish")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should capture with an explicit hash" do
|
138
|
+
dispatch(:body => 'hola jeannette gessler', :from => 'bradgessler').should eql("hello jeannette gessler in spanish")
|
126
139
|
end
|
127
140
|
end
|
128
141
|
|
129
142
|
context "context" do
|
130
143
|
it "should handle contexts and non-proc conditions" do
|
131
|
-
|
144
|
+
dispatch('HI BRAD 90').should eql("STOP SHOUTING WITH NUMBERS!")
|
132
145
|
end
|
133
146
|
|
134
147
|
it "should handle nested contexts and proc conditions" do
|
135
|
-
|
148
|
+
dispatch('HI BRAD').should eql("STOP SHOUTING WITHOUT NUMBERS!")
|
136
149
|
end
|
137
150
|
|
138
151
|
it "should pass arguments into contexts" do
|
139
|
-
|
152
|
+
dispatch('FUNNYWORD').should eql("Zeldzamar-1080")
|
140
153
|
end
|
141
154
|
end
|
142
155
|
end
|
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: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brad Gessler
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-08-02 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -29,7 +29,6 @@ extensions: []
|
|
29
29
|
extra_rdoc_files: []
|
30
30
|
|
31
31
|
files:
|
32
|
-
- .document
|
33
32
|
- .gitignore
|
34
33
|
- .rvmrc
|
35
34
|
- Gemfile
|