joshbuddy-usher 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +20 -2
- data/VERSION.yml +1 -1
- data/lib/usher/interface/email_interface.rb +31 -0
- data/lib/usher/interface.rb +4 -0
- data/lib/usher/node.rb +7 -4
- data/lib/usher/route/variable.rb +3 -2
- data/lib/usher/splitter.rb +5 -6
- data/lib/usher.rb +35 -9
- data/spec/private/email/recognize_spec.rb +40 -0
- data/spec/private/split_spec.rb +16 -12
- metadata +5 -2
data/README.rdoc
CHANGED
@@ -43,9 +43,25 @@ However, <tt>/path/test/one_more/path</tt> would not be matched.
|
|
43
43
|
|
44
44
|
In the above examples, ['one', 'two', 'three'] and ['four', 'five'] respectively would be bound to the key :variable.
|
45
45
|
|
46
|
+
As well, variables can have a regex matcher.
|
47
|
+
|
48
|
+
<b>Example:</b>
|
49
|
+
<tt>/product/{:id,\d+}</tt> would match
|
50
|
+
|
51
|
+
* <tt>/product/123</tt>
|
52
|
+
* <tt>/product/4521</tt>
|
53
|
+
|
54
|
+
But not
|
55
|
+
* <tt>/product/AE-35</tt>
|
56
|
+
|
57
|
+
As well, the same logic applies for * variables as well, where only parts matchable by the supplied regex will
|
58
|
+
actually be bound to the variable
|
59
|
+
|
46
60
|
==== Static
|
47
61
|
|
48
62
|
Static parts of literal character sequences. For instance, <tt>/path/something.html</tt> would match only the same path.
|
63
|
+
As well, static parts can have a regex pattern in them as well, such as <tt>/path/something.{html|xml}</tt> which would match only
|
64
|
+
<tt>/path/something.html</tt> and <tt>/path/something.xml</tt>
|
49
65
|
|
50
66
|
==== Optional sections
|
51
67
|
|
@@ -53,12 +69,14 @@ Sections of a route can be marked as optional by surrounding it with brackets. F
|
|
53
69
|
|
54
70
|
==== One and only one sections
|
55
71
|
|
56
|
-
Sections of a route can be marked as "one and only one" by surrounding it with brackets and separating parts of the route with pipes.
|
72
|
+
Sections of a route can be marked as "one and only one" by surrounding it with brackets and separating parts of the route with pipes.
|
73
|
+
For instance, the path, <tt>/path/something(.xml|.html)</tt> would only match <tt>/path/something.xml</tt> and
|
74
|
+
<tt>/path/something.html</tt>. Generally its more efficent to use one and only sections over using regex.
|
57
75
|
|
58
76
|
=== +options+
|
59
77
|
* +transformers+ - Transforms a variable before it gets to the requirements. Takes either a +proc+ or a +symbol+. If its a +symbol+, calls the method on the incoming parameter. If its a +proc+, its called with the variable.
|
60
78
|
* +requirements+ - After transformation, tests the condition using ===. If it returns false, it raises an <tt>Usher::ValidationException</tt>
|
61
|
-
* +conditions+ - Accepts any of the
|
79
|
+
* +conditions+ - Accepts any of the +request_methods+ specificied in the construction of Usher. This can be either a <tt>string</tt> or a regular expression.
|
62
80
|
* Any other key is interpreted as a requirement for the variable of its name.
|
63
81
|
|
64
82
|
== Rails
|
data/VERSION.yml
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'rack_interface/route'
|
4
|
+
|
5
|
+
class Usher
|
6
|
+
module Interface
|
7
|
+
class EmailInterface
|
8
|
+
|
9
|
+
def initialize(&blk)
|
10
|
+
@routes = Usher.new(:delimiters => ['@', '-', '.'], :valid_regex => '[\+a-zA-Z0-9]+', :globs_capture_separators => true)
|
11
|
+
instance_eval(&blk) if blk
|
12
|
+
end
|
13
|
+
|
14
|
+
def for(path, &block)
|
15
|
+
@routes.add_route(path).to(block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def reset!
|
19
|
+
@routes.reset!
|
20
|
+
end
|
21
|
+
|
22
|
+
def act(email)
|
23
|
+
response = @routes.recognize(email, email)
|
24
|
+
if response.path
|
25
|
+
response.path.route.params.first.call(response.params.inject({}){|h,(k,v)| h[k]=v.to_s; h })
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/usher/interface.rb
CHANGED
@@ -5,6 +5,7 @@ class Usher
|
|
5
5
|
autoload :Rails2Interface, 'interface/rails2_interface'
|
6
6
|
autoload :MerbInterface, 'interface/merb_interface'
|
7
7
|
autoload :RackInterface, 'interface/rack_interface'
|
8
|
+
autoload :EmailInterface, 'interface/email_interface'
|
8
9
|
|
9
10
|
def self.for(type, &blk)
|
10
11
|
case type
|
@@ -14,7 +15,10 @@ class Usher
|
|
14
15
|
MerbInterface.new(&blk)
|
15
16
|
when :rack
|
16
17
|
RackInterface.new(&blk)
|
18
|
+
when :email
|
19
|
+
EmailInterface.new(&blk)
|
17
20
|
end
|
21
|
+
|
18
22
|
end
|
19
23
|
|
20
24
|
|
data/lib/usher/node.rb
CHANGED
@@ -9,7 +9,7 @@ class Usher
|
|
9
9
|
Response = Struct.new(:path, :params)
|
10
10
|
|
11
11
|
attr_reader :lookup
|
12
|
-
attr_accessor :terminates, :exclusive_type, :parent, :value, :request_methods
|
12
|
+
attr_accessor :terminates, :exclusive_type, :parent, :value, :request_methods, :globs_capture_separators
|
13
13
|
|
14
14
|
def initialize(parent, value)
|
15
15
|
@parent = parent
|
@@ -26,9 +26,10 @@ class Usher
|
|
26
26
|
@depth ||= @parent && @parent.is_a?(Node) ? @parent.depth + 1 : 0
|
27
27
|
end
|
28
28
|
|
29
|
-
def self.root(route_set, request_methods)
|
29
|
+
def self.root(route_set, request_methods, globs_capture_separators)
|
30
30
|
root = self.new(route_set, nil)
|
31
31
|
root.request_methods = request_methods
|
32
|
+
root.globs_capture_separators = globs_capture_separators
|
32
33
|
root
|
33
34
|
end
|
34
35
|
|
@@ -69,6 +70,8 @@ class Usher
|
|
69
70
|
current_node.lookup[nil] ||= Node.new(current_node, Route::RequestMethod.new(current_node.exclusive_type, nil))
|
70
71
|
end
|
71
72
|
else
|
73
|
+
key.globs_capture_separators = globs_capture_separators if key.is_a?(Route::Variable)
|
74
|
+
|
72
75
|
if !key.is_a?(Route::Variable)
|
73
76
|
current_node.upgrade_lookup if key.is_a?(Regexp)
|
74
77
|
current_node.lookup[key] ||= Node.new(current_node, key)
|
@@ -116,7 +119,7 @@ class Usher
|
|
116
119
|
path.unshift(next_part.parent.value) if next_part.parent.value.is_a?(Symbol)
|
117
120
|
break
|
118
121
|
else
|
119
|
-
unless part.is_a?(Symbol)
|
122
|
+
unless part.is_a?(Symbol) && !next_part.value.globs_capture_separators
|
120
123
|
part = next_part.value.transform!(part)
|
121
124
|
next_part.value.valid!(part)
|
122
125
|
params.last.last << part
|
@@ -152,7 +155,7 @@ class Usher
|
|
152
155
|
path.unshift(next_part.parent.value) if next_part.parent.value.is_a?(Symbol)
|
153
156
|
next_part.find(request, path, params)
|
154
157
|
else
|
155
|
-
unless part.is_a?(Symbol)
|
158
|
+
unless part.is_a?(Symbol) && !next_part.value.globs_capture_separators
|
156
159
|
part = next_part.value.transform!(part)
|
157
160
|
next_part.value.valid!(part)
|
158
161
|
params.last.last << part
|
data/lib/usher/route/variable.rb
CHANGED
@@ -2,14 +2,15 @@ class Usher
|
|
2
2
|
class Route
|
3
3
|
class Variable
|
4
4
|
attr_reader :type, :name, :validator, :transformer, :regex_matcher
|
5
|
-
attr_accessor :look_ahead
|
5
|
+
attr_accessor :look_ahead, :globs_capture_separators
|
6
6
|
|
7
|
-
def initialize(type, name, validator = nil, transformer = nil, regex_matcher = nil)
|
7
|
+
def initialize(type, name, validator = nil, transformer = nil, regex_matcher = nil, globs_capture_separators = false)
|
8
8
|
@type = type
|
9
9
|
@name = :"#{name}"
|
10
10
|
@validator = validator
|
11
11
|
@transformer = transformer
|
12
12
|
@regex_matcher = regex_matcher
|
13
|
+
@globs_capture_separators = globs_capture_separators
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_s
|
data/lib/usher/splitter.rb
CHANGED
@@ -3,13 +3,12 @@ require 'strscan'
|
|
3
3
|
class Usher
|
4
4
|
class Splitter
|
5
5
|
|
6
|
-
def self.for_delimiters(delimiters)
|
6
|
+
def self.for_delimiters(delimiters, valid_regex)
|
7
7
|
delimiters_regex = delimiters.collect{|d| Regexp.quote(d)} * '|'
|
8
|
-
|
9
8
|
SplitterInstance.new(
|
10
9
|
delimiters,
|
11
|
-
Regexp.new('((:|\*)?
|
12
|
-
Regexp.new(delimiters_regex + '|
|
10
|
+
Regexp.new('((:|\*)?' + valid_regex + '|' + delimiters_regex + '|\(|\)|\||\{)'),
|
11
|
+
Regexp.new(delimiters_regex + '|' + valid_regex)
|
13
12
|
)
|
14
13
|
end
|
15
14
|
|
@@ -51,7 +50,7 @@ class Usher
|
|
51
50
|
type = part.slice!(0).chr.to_sym
|
52
51
|
current_group << Usher::Route::Variable.new(type, part, requirements && requirements[part.to_sym], transformers && transformers[part.to_sym])
|
53
52
|
when ?{
|
54
|
-
pattern = ''
|
53
|
+
pattern = '^'
|
55
54
|
count = 1
|
56
55
|
variable = ss.scan(/[:\*]([^,]+),/)
|
57
56
|
until count.zero?
|
@@ -64,7 +63,7 @@ class Usher
|
|
64
63
|
end
|
65
64
|
pattern << regex_part
|
66
65
|
end
|
67
|
-
pattern
|
66
|
+
pattern[pattern.size - 1] = ?$
|
68
67
|
regex = Regexp.new(pattern)
|
69
68
|
if variable
|
70
69
|
variable_type = variable.slice!(0).chr.to_sym
|
data/lib/usher.rb
CHANGED
@@ -31,7 +31,7 @@ class Usher
|
|
31
31
|
# set.reset!
|
32
32
|
# set.empty? => true
|
33
33
|
def reset!
|
34
|
-
@tree = Node.root(self, @request_methods)
|
34
|
+
@tree = Node.root(self, @request_methods, @globs_capture_separators)
|
35
35
|
@named_routes = {}
|
36
36
|
@routes = []
|
37
37
|
@route_count = 0
|
@@ -39,16 +39,24 @@ class Usher
|
|
39
39
|
end
|
40
40
|
alias clear! reset!
|
41
41
|
|
42
|
-
# Creates a route set, with
|
42
|
+
# Creates a route set, with options
|
43
43
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
44
|
+
# <tt>:globs_capture_separators</tt>: +true+ or +false+. (default +false+) Specifies whether glob matching will also include separators
|
45
|
+
# that are matched.
|
46
|
+
#
|
47
|
+
# <tt>:delimiters</tt>: Array of Strings. (default <tt>['/', '.']</tt>). Delimiters used in path separation. Array must be single character strings.
|
48
|
+
#
|
49
|
+
# <tt>:valid_regex</tt>: String. (default <tt>'[0-9A-Za-z\$\-_\+!\*\',]+'</tt>). String that can be interpolated into regex to match
|
50
|
+
# valid character sequences within path.
|
51
|
+
#
|
52
|
+
# <tt>:request_methods</tt>: Array of Symbols. (default <tt>[:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]</tt>)
|
53
|
+
# Array of methods called against the request object for the purposes of matching route requirements.
|
48
54
|
def initialize(options = nil)
|
49
|
-
@
|
55
|
+
@globs_capture_separators = options && options.key?(:globs_capture_separators) ? options.delete(:globs_capture_separators) : false
|
56
|
+
@delimiters = options && options.delete(:delimiters) || ['/', '.']
|
57
|
+
@valid_regex = options && options.delete(:valid_regex) || '[0-9A-Za-z\$\-_\+!\*\',]+'
|
50
58
|
@request_methods = options && options.delete(:request_methods) || [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]
|
51
|
-
@splitter = Splitter.for_delimiters(@delimiters)
|
59
|
+
@splitter = Splitter.for_delimiters(@delimiters, @valid_regex)
|
52
60
|
reset!
|
53
61
|
end
|
54
62
|
|
@@ -96,9 +104,25 @@ class Usher
|
|
96
104
|
#
|
97
105
|
# In the above examples, ['one', 'two', 'three'] and ['four', 'five'] respectively would be bound to the key :variable.
|
98
106
|
#
|
107
|
+
# As well, variables can have a regex matcher.
|
108
|
+
#
|
109
|
+
# <b>Example:</b>
|
110
|
+
# <tt>/product/{:id,\d+}</tt> would match
|
111
|
+
#
|
112
|
+
# * <tt>/product/123</tt>
|
113
|
+
# * <tt>/product/4521</tt>
|
114
|
+
#
|
115
|
+
# But not
|
116
|
+
# * <tt>/product/AE-35</tt>
|
117
|
+
#
|
118
|
+
# As well, the same logic applies for * variables as well, where only parts matchable by the supplied regex will
|
119
|
+
# actually be bound to the variable
|
120
|
+
#
|
99
121
|
# ==== Static
|
100
122
|
#
|
101
123
|
# Static parts of literal character sequences. For instance, <tt>/path/something.html</tt> would match only the same path.
|
124
|
+
# As well, static parts can have a regex pattern in them as well, such as <tt>/path/something.{html|xml}</tt> which would match only
|
125
|
+
# <tt>/path/something.html</tt> and <tt>/path/something.xml</tt>
|
102
126
|
#
|
103
127
|
# ==== Optional sections
|
104
128
|
#
|
@@ -106,7 +130,9 @@ class Usher
|
|
106
130
|
#
|
107
131
|
# ==== One and only one sections
|
108
132
|
#
|
109
|
-
# Sections of a route can be marked as "one and only one" by surrounding it with brackets and separating parts of the route with pipes.
|
133
|
+
# Sections of a route can be marked as "one and only one" by surrounding it with brackets and separating parts of the route with pipes.
|
134
|
+
# For instance, the path, <tt>/path/something(.xml|.html)</tt> would only match <tt>/path/something.xml</tt> and
|
135
|
+
# <tt>/path/something.html</tt>. Generally its more efficent to use one and only sections over using regex.
|
110
136
|
#
|
111
137
|
# === +options+
|
112
138
|
# * +transformers+ - Transforms a variable before it gets to the requirements. Takes either a +proc+ or a +symbol+. If its a +symbol+, calls the method on the incoming parameter. If its a +proc+, its called with the variable.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'lib/usher'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
def build_email_mock(email)
|
6
|
+
request = mock "Request"
|
7
|
+
request.should_receive(:email).any_number_of_times.and_return(email)
|
8
|
+
request
|
9
|
+
end
|
10
|
+
|
11
|
+
SampleController = Object.new
|
12
|
+
|
13
|
+
describe "Usher (for email) route recognition" do
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
@route_set = Usher::Interface.for(:email)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should recognize a simple request" do
|
20
|
+
receiver = mock('receiver')
|
21
|
+
receiver.should_receive(:action).with({}).exactly(1)
|
22
|
+
@route_set.for('joshbuddy@gmail.com') { |params| receiver.action(params) }
|
23
|
+
@route_set.act('joshbuddy@gmail.com')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should recognize a wildcard domain" do
|
27
|
+
receiver = mock('receiver')
|
28
|
+
receiver.should_receive(:action).with({:domain => 'gmail.com'}).exactly(1)
|
29
|
+
@route_set.for('joshbuddy@*domain') { |params| receiver.action(params) }
|
30
|
+
@route_set.act('joshbuddy@gmail.com')
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should recognize a complex email" do
|
34
|
+
receiver = mock('receiver')
|
35
|
+
receiver.should_receive(:action).with({:subject => 'sub+ect', :id => '123', :sid => '456', :tok => 'sdqwe123ae', :domain => 'mydomain.org'}).exactly(1)
|
36
|
+
@route_set.for(':subject.{:id,^\d+$}-{:sid,^\d+$}-{:tok,^\w+$}@*domain') { |params| receiver.action(params) }
|
37
|
+
@route_set.act('sub+ect.123-456-sdqwe123ae@mydomain.org')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/spec/private/split_spec.rb
CHANGED
@@ -4,38 +4,42 @@ describe "Usher route tokenizing" do
|
|
4
4
|
|
5
5
|
|
6
6
|
it "should split / delimited routes" do
|
7
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/test/this/split').should == [[:/, 'test', :/,'this', :/, 'split']]
|
7
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this/split').should == [[:/, 'test', :/,'this', :/, 'split']]
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should split / delimited routes with a regex in it" do
|
11
|
-
Usher::Splitter.for_delimiters(['/', '.']).
|
12
|
-
split('/test/{this}/split').should == [[:/, 'test', :/,
|
11
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').
|
12
|
+
split('/test/{this}/split').should == [[:/, 'test', :/, /^this$/, :/, 'split']]
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should split on ' ' delimited routes as well" do
|
16
|
-
Usher::Splitter.for_delimiters([' ']).split('test this split').should == [['test', :' ', 'this', :' ', 'split']]
|
16
|
+
Usher::Splitter.for_delimiters([' '], '[0-9A-Za-z\$\-_\+!\*\',]+').split('test this split').should == [['test', :' ', 'this', :' ', 'split']]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should split on email delimiters as well" do
|
20
|
+
Usher::Splitter.for_delimiters(['@', '+', '-', '.'], '[a-zA-Z0-9]+').split('one+more.12345-09876-alphanum3ric5@domain.com').should == [["one", :+, "more", :".", "12345", :-, "09876", :-, "alphanum3ric5", :"@", "domain", :".", "com"]]
|
17
21
|
end
|
18
22
|
|
19
23
|
it "should split on ' ' delimited routes for more complex routes as well" do
|
20
|
-
Usher::Splitter.for_delimiters([' ']).split('(test|this) split').should == [['test', :' ', 'split'], ['this', :' ', 'split']]
|
24
|
+
Usher::Splitter.for_delimiters([' '], '[0-9A-Za-z\$\-_\+!\*\',]+').split('(test|this) split').should == [['test', :' ', 'split'], ['this', :' ', 'split']]
|
21
25
|
end
|
22
26
|
|
23
27
|
it "should group optional parts with brackets" do
|
24
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/test/this(/split)').should == [
|
28
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split)').should == [
|
25
29
|
[:/, 'test', :/, 'this'],
|
26
30
|
[:/, 'test', :/, 'this', :/, 'split']
|
27
31
|
]
|
28
32
|
end
|
29
33
|
|
30
34
|
it "should group exclusive optional parts with brackets and pipes" do
|
31
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/test/this(/split|/split2)').should == [
|
35
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split|/split2)').should == [
|
32
36
|
[:/, 'test', :/, 'this',:/, 'split'],
|
33
37
|
[:/, 'test', :/, 'this',:/, 'split2']
|
34
38
|
]
|
35
39
|
end
|
36
40
|
|
37
41
|
it "should group exclusive optional-optional parts with brackets and pipes" do
|
38
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/test/this((/split|/split2))').should == [
|
42
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this((/split|/split2))').should == [
|
39
43
|
[:/, 'test',:/, 'this'],
|
40
44
|
[:/, 'test',:/, 'this', :/, 'split'],
|
41
45
|
[:/, 'test',:/, 'this', :/, 'split2']
|
@@ -43,7 +47,7 @@ describe "Usher route tokenizing" do
|
|
43
47
|
end
|
44
48
|
|
45
49
|
it "should group optional parts with brackets (for non overlapping groups)" do
|
46
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/test/this(/split)(/split2)') == [
|
50
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split)(/split2)') == [
|
47
51
|
[:/, "test", :/, "this"],
|
48
52
|
[:/, "test", :/, "this", :/, "split"],
|
49
53
|
[:/, "test", :/, "this", :/, "split2"],
|
@@ -52,7 +56,7 @@ describe "Usher route tokenizing" do
|
|
52
56
|
end
|
53
57
|
|
54
58
|
it "should group nested-optional parts with brackets" do
|
55
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/test/this(/split(.:format))') == [
|
59
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split(.:format))') == [
|
56
60
|
[:/, "test", :/, "this"],
|
57
61
|
[:/, "test", :/, "this", :/, "split"],
|
58
62
|
[:/, "test", :/, "this", :/, "split", :'.', Usher::Route::Variable.new(:':', :format)]
|
@@ -60,12 +64,12 @@ describe "Usher route tokenizing" do
|
|
60
64
|
end
|
61
65
|
|
62
66
|
it "should to_s all different variable types" do
|
63
|
-
Usher::Splitter.for_delimiters(['/', '.']).split('/:split/*splitter').first.collect{|v| v.to_s} ==
|
67
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/:split/*splitter').first.collect{|v| v.to_s} ==
|
64
68
|
[ ':split', '*splitter' ]
|
65
69
|
end
|
66
70
|
|
67
71
|
it "should == variable types" do
|
68
|
-
parts = Usher::Splitter.for_delimiters(['/', '.']).split('/:split/:split').first
|
72
|
+
parts = Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/:split/:split').first
|
69
73
|
parts[1].should == parts[3]
|
70
74
|
end
|
71
75
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joshbuddy-usher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Hull
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-11 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- lib/usher/exceptions.rb
|
41
41
|
- lib/usher/grapher.rb
|
42
42
|
- lib/usher/interface
|
43
|
+
- lib/usher/interface/email_interface.rb
|
43
44
|
- lib/usher/interface/merb_interface.rb
|
44
45
|
- lib/usher/interface/rack_interface
|
45
46
|
- lib/usher/interface/rack_interface/mapper.rb
|
@@ -58,6 +59,8 @@ files:
|
|
58
59
|
- lib/usher/splitter.rb
|
59
60
|
- lib/usher.rb
|
60
61
|
- spec/private
|
62
|
+
- spec/private/email
|
63
|
+
- spec/private/email/recognize_spec.rb
|
61
64
|
- spec/private/generate_spec.rb
|
62
65
|
- spec/private/grapher_spec.rb
|
63
66
|
- spec/private/path_spec.rb
|