joshbuddy-usher 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 2
3
- :patch: 2
4
2
  :major: 0
3
+ :minor: 3
4
+ :patch: 0
@@ -4,10 +4,11 @@ require 'usher/node'
4
4
  require 'usher/route'
5
5
  require 'usher/grapher'
6
6
  require 'usher/interface'
7
+ require 'usher/splitter'
7
8
  require 'usher/exceptions'
8
9
 
9
10
  class Usher
10
- attr_reader :tree, :named_routes, :route_count, :routes
11
+ attr_reader :tree, :named_routes, :route_count, :routes, :splitter
11
12
 
12
13
  SymbolArraySorter = proc {|a,b| a.hash <=> b.hash} #:nodoc:
13
14
 
@@ -38,7 +39,8 @@ class Usher
38
39
  alias clear! reset!
39
40
 
40
41
  # Creates a route set
41
- def initialize
42
+ def initialize(delimiter = '/')
43
+ @splitter = Splitter.delimiter(delimiter)
42
44
  reset!
43
45
  end
44
46
 
@@ -130,7 +132,7 @@ class Usher
130
132
  # route = set.add_route('/test')
131
133
  # set.recognize(Request.new('/test')).path.route == route => true
132
134
  def recognize(request)
133
- @tree.find(request)
135
+ @tree.find(request, @splitter.url_split(request.path))
134
136
  end
135
137
 
136
138
  # Recognizes a set of +parameters+ and gets the closest matching Usher::Route::Path or +nil+ if no route exists.
@@ -1,7 +1,5 @@
1
1
  class Usher
2
2
  class UnrecognizedException < RuntimeError; end
3
- class ValidationException < RuntimeError
4
-
5
- end
3
+ class ValidationException < RuntimeError; end
6
4
  class MissingParameterException < RuntimeError; end
7
5
  end
@@ -21,14 +21,7 @@ class Usher
21
21
  end
22
22
 
23
23
  def depth
24
- unless @depth
25
- @depth = 0
26
- p = self
27
- while (p = p.parent) && p.is_a?(Node)
28
- @depth += 1
29
- end
30
- end
31
- @depth
24
+ @depth ||= @parent && @parent.is_a?(Node) ? @parent.depth + 1 : 0
32
25
  end
33
26
 
34
27
  def self.root(route_set)
@@ -103,7 +96,7 @@ class Usher
103
96
  route
104
97
  end
105
98
 
106
- def find(request, path = Route::Splitter.url_split(request.path), params = [])
99
+ def find(request, path, params = [])
107
100
  part = path.shift unless path.size.zero?
108
101
 
109
102
  if @exclusive_type
@@ -1,7 +1,6 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  require 'route/path'
4
- require 'route/splitter'
5
4
  require 'route/variable'
6
5
  require 'route/request_method'
7
6
 
@@ -15,7 +14,7 @@ class Usher
15
14
  @requirements = options.delete(:requirements)
16
15
  @conditions = options.delete(:conditions)
17
16
  @transformers = options.delete(:transformers)
18
- @paths = Splitter.new(@original_path, @requirements, @transformers).paths.collect {|path| Path.new(self, path)}
17
+ @paths = @router.splitter.split(@original_path, @requirements, @transformers).collect {|path| Path.new(self, path)}
19
18
  @primary_path = @paths.first
20
19
  end
21
20
 
@@ -1,47 +1,53 @@
1
1
  require 'strscan'
2
2
 
3
3
  class Usher
4
- class Route
5
- class Splitter
6
-
7
- ScanRegex = /((:|\*||\.:|\.)[0-9A-Za-z\$\-_\+!\*',]+|\/|\(|\)|\|)/
8
- UrlScanRegex = /\/|\.?[0-9A-Za-z\$\-_\+!\*',]+/
9
-
10
- attr_reader :paths
4
+ class Splitter
5
+
6
+ def self.delimiter(delimiter = '/')
7
+ SplitterInstance.new(
8
+ delimiter,
9
+ Regexp.new('((:|\*||\.:|\.)[0-9A-Za-z\$\-_\+!\*\',]+|' + Regexp.quote(delimiter) + '|\(|\)|\|)'),
10
+ Regexp.new(Regexp.quote(delimiter) + '|\.?[0-9A-Za-z\$\-_\+!\*\',]+')
11
+ )
12
+ end
13
+
14
+ attr_reader :paths
15
+
16
+ class SplitterInstance
11
17
 
12
- def initialize(path, requirements = {}, transformers = {})
13
- @parts = Splitter.split(path, requirements, transformers)
14
- @paths = calc_paths(@parts)
15
- @paths
18
+ def initialize(delimiter, split_regex, url_split_regex)
19
+ @delimiter = delimiter
20
+ @split_regex = split_regex
21
+ @url_split_regex = url_split_regex
16
22
  end
17
-
18
- def self.url_split(path)
23
+
24
+ def url_split(path)
19
25
  parts = []
20
26
  ss = StringScanner.new(path)
21
27
  while !ss.eos?
22
- if part = ss.scan(UrlScanRegex)
23
- parts << part unless part == '/'
28
+ if part = ss.scan(@url_split_regex)
29
+ parts << part unless part == @delimiter
24
30
  end
25
31
  end if path && !path.empty?
26
32
  parts
27
33
  end
28
-
29
- def self.split(path, requirements = {}, transformers = {})
34
+
35
+ def split(path, requirements = {}, transformers = {})
30
36
  parts = Group.new(:all, nil)
31
37
  ss = StringScanner.new(path)
32
38
  current_group = parts
33
39
  while !ss.eos?
34
- part = ss.scan(ScanRegex)
40
+ part = ss.scan(@split_regex)
35
41
  case part[0]
36
42
  when ?*, ?:, ?.
37
43
  type = (part[1] == ?: ? part.slice!(0,2) : part.slice!(0).chr).to_sym
38
- current_group << Variable.new(type, part, :validator => requirements[part.to_sym], :transformer => transformers[part.to_sym])
44
+ current_group << Usher::Route::Variable.new(type, part, :validator => requirements[part.to_sym], :transformer => transformers[part.to_sym])
39
45
  when ?(
40
46
  new_group = Group.new(:any, current_group)
41
47
  current_group << new_group
42
48
  current_group = new_group
43
- when ?)
44
- current_group = current_group.parent
49
+ when ?)
50
+ current_group = current_group.parent.type == :one ? current_group.parent.parent : current_group.parent
45
51
  when ?|
46
52
  unless current_group.parent.type == :one
47
53
  detached_group = current_group.parent.pop
@@ -53,16 +59,16 @@ class Usher
53
59
  end
54
60
  current_group.parent << Group.new(:all, current_group.parent)
55
61
  current_group = current_group.parent.last
56
- when ?/
62
+ when @delimiter[0]
57
63
  else
58
64
  current_group << part
59
65
  end
60
66
  end unless !path || path.empty?
61
- parts
67
+ calc_paths(parts)
62
68
  end
63
-
69
+
64
70
  private
65
-
71
+
66
72
  def cartesian_product!(lval, rval)
67
73
  product = []
68
74
  (lval.size * rval.size).times do |index|
@@ -73,7 +79,7 @@ class Usher
73
79
  end
74
80
  lval.replace(product)
75
81
  end
76
-
82
+
77
83
  def calc_paths(parts)
78
84
  if parts.is_a?(Group)
79
85
  paths = [[]]
@@ -97,23 +103,23 @@ class Usher
97
103
  else
98
104
  [[parts]]
99
105
  end
100
-
106
+
101
107
  end
108
+ end
109
+
110
+ class Group < Array
111
+ attr_accessor :type
112
+ attr_accessor :parent
102
113
 
103
- class Group < Array
104
- attr_accessor :type
105
- attr_accessor :parent
106
-
107
- def inspect
108
- "#{type}->#{super}"
109
- end
110
-
111
- def initialize(type, parent)
112
- @type = type
113
- @parent = parent
114
- end
114
+ def inspect
115
+ "#{type}->#{super}"
115
116
  end
116
117
 
118
+ def initialize(type, parent)
119
+ @type = type
120
+ @parent = parent
121
+ end
117
122
  end
123
+
118
124
  end
119
125
  end
@@ -4,25 +4,33 @@ describe "Usher route tokenizing" do
4
4
 
5
5
 
6
6
  it "should split / delimited routes" do
7
- Usher::Route::Splitter.new('/test/this/split').paths.first.should == ['test', 'this', 'split']
7
+ Usher::Splitter.delimiter('/').split('/test/this/split').should == [['test', 'this', 'split']]
8
+ end
9
+
10
+ it "should split on ' ' delimited routes as well" do
11
+ Usher::Splitter.delimiter(' ').split('test this split').should == [['test', 'this', 'split']]
12
+ end
13
+
14
+ it "should split on ' ' delimited routes for more complex routes as well" do
15
+ Usher::Splitter.delimiter(' ').split('(test|this) split').should == [['test', 'split'], ['this', 'split']]
8
16
  end
9
17
 
10
18
  it "should group optional parts with brackets" do
11
- Usher::Route::Splitter.new('/test/this(/split)').paths.should == [
19
+ Usher::Splitter.delimiter('/').split('/test/this(/split)').should == [
12
20
  ['test', 'this'],
13
21
  ['test', 'this', 'split']
14
22
  ]
15
23
  end
16
24
 
17
25
  it "should group exclusive optional parts with brackets and pipes" do
18
- Usher::Route::Splitter.new('/test/this(/split|/split2)').paths.should == [
26
+ Usher::Splitter.delimiter('/').split('/test/this(/split|/split2)').should == [
19
27
  ['test', 'this', 'split'],
20
28
  ['test', 'this', 'split2']
21
29
  ]
22
30
  end
23
31
 
24
32
  it "should group exclusive optional-optional parts with brackets and pipes" do
25
- Usher::Route::Splitter.new('/test/this((/split|/split2))').paths.should == [
33
+ Usher::Splitter.delimiter('/').split('/test/this((/split|/split2))').should == [
26
34
  ['test', 'this'],
27
35
  ['test', 'this', 'split'],
28
36
  ['test', 'this', 'split2']
@@ -30,7 +38,7 @@ describe "Usher route tokenizing" do
30
38
  end
31
39
 
32
40
  it "should group optional parts with brackets (for non overlapping groups)" do
33
- Usher::Route::Splitter.new('/test/this(/split)(/split2)').paths == [
41
+ Usher::Splitter.delimiter('/').split('/test/this(/split)(/split2)') == [
34
42
  ["test", "this"],
35
43
  ["test", "this", "split"],
36
44
  ["test", "this", "split2"],
@@ -39,7 +47,7 @@ describe "Usher route tokenizing" do
39
47
  end
40
48
 
41
49
  it "should group nested-optional parts with brackets" do
42
- Usher::Route::Splitter.new('/test/this(/split(.:format))').paths == [
50
+ Usher::Splitter.delimiter('/').split('/test/this(/split(.:format))') == [
43
51
  ["test", "this"],
44
52
  ["test", "this", "split"],
45
53
  ["test", "this", "split", Usher::Route::Variable.new(:'.:', :format)]
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.2.2
4
+ version: 0.3.0
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-04-02 00:00:00 -07:00
12
+ date: 2009-04-03 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -53,9 +53,9 @@ files:
53
53
  - lib/usher/route
54
54
  - lib/usher/route/path.rb
55
55
  - lib/usher/route/request_method.rb
56
- - lib/usher/route/splitter.rb
57
56
  - lib/usher/route/variable.rb
58
57
  - lib/usher/route.rb
58
+ - lib/usher/splitter.rb
59
59
  - lib/usher.rb
60
60
  - spec/generate_spec.rb
61
61
  - spec/grapher_spec.rb