joshbuddy-usher 0.3.2 → 0.3.3

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/Rakefile CHANGED
@@ -27,3 +27,10 @@ namespace(:spec) do
27
27
  end
28
28
 
29
29
  end
30
+
31
+ desc "Run all examples with RCov"
32
+ Spec::Rake::SpecTask.new('spec_with_rcov') do |t|
33
+ t.spec_files = FileList['spec/**/*.rb']
34
+ t.rcov = true
35
+ t.rcov_opts = ['--exclude', 'spec']
36
+ end
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 3
3
- :patch: 2
2
+ :patch: 3
4
3
  :major: 0
4
+ :minor: 3
@@ -44,10 +44,10 @@ class Usher
44
44
  # The +request_methods+ are methods that are called against the request object in order to
45
45
  # enforce the +conditions+ segment of the routes. For HTTP routes (and in fact the default), those
46
46
  # methods are <tt>[:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method]</tt>.
47
- def initialize(delimiters = ['/', '.'], request_methods = [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method])
48
- @delimiters = delimiters
49
- @splitter = Splitter.for_delimiters(delimiters)
50
- @request_methods = request_methods
47
+ def initialize(options = {})
48
+ @delimiters = options.delete(:options) || ['/', '.']
49
+ @request_methods = options.delete(:request_methods) || [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]
50
+ @splitter = Splitter.for_delimiters(@delimiters)
51
51
  reset!
52
52
  end
53
53
 
@@ -117,7 +117,7 @@ class Usher
117
117
  conditions = options.delete(:conditions) || {}
118
118
  requirements = options.delete(:requirements) || {}
119
119
  options.delete_if do |k, v|
120
- if v.is_a?(Regexp)
120
+ if v.is_a?(Regexp) || v.is_a?(Proc)
121
121
  requirements[k] = v
122
122
  true
123
123
  end
@@ -173,7 +173,7 @@ class Usher
173
173
  else
174
174
  route
175
175
  end
176
-
176
+ raise UnrecognizedException.new unless path
177
177
  params_hash = {}
178
178
  param_list = case params
179
179
  when Hash
@@ -16,7 +16,6 @@ class Usher
16
16
  @value = value
17
17
  @lookup = FuzzyHash.new
18
18
  @exclusive_type = nil
19
- @has_globber = find_parent{|p| p.value && p.value.is_a?(Route::Variable)}
20
19
  end
21
20
 
22
21
  def depth
@@ -29,28 +28,10 @@ class Usher
29
28
  root
30
29
  end
31
30
 
32
- def has_globber?
33
- @has_globber
34
- end
35
-
36
31
  def terminates?
37
32
  @terminates
38
33
  end
39
34
 
40
- def find_parent(&blk)
41
- if @parent.nil? || !@parent.is_a?(Node)
42
- nil
43
- elsif yield @parent
44
- @parent
45
- else #keep searching
46
- @parent.find_parent(&blk)
47
- end
48
- end
49
-
50
- def replace(src, dest)
51
- @lookup.replace(src, dest)
52
- end
53
-
54
35
  def pp
55
36
  $stdout << " " * depth
56
37
  $stdout << "#{depth}: #{value.inspect} #{!!terminates?}\n"
@@ -83,12 +64,7 @@ class Usher
83
64
  current_node.lookup[nil] ||= Node.new(current_node, Route::RequestMethod.new(current_node.exclusive_type, nil))
84
65
  end
85
66
  else
86
- if current_node.exclusive_type
87
- parts.unshift(key)
88
- current_node.lookup[nil] ||= Node.new(current_node, Route::RequestMethod.new(current_node.exclusive_type, nil))
89
- else
90
- current_node.lookup[key.is_a?(Route::Variable) ? nil : key] ||= Node.new(current_node, key)
91
- end
67
+ current_node.lookup[key.is_a?(Route::Variable) ? nil : key] ||= Node.new(current_node, key)
92
68
  end
93
69
  current_node = target_node
94
70
  end
@@ -109,8 +85,8 @@ class Usher
109
85
  elsif path.size.zero? && !part
110
86
  if terminates?
111
87
  Response.new(terminates, params)
112
- else
113
- nil
88
+ elsif params.last.is_a?(Array) && @lookup[nil]
89
+ Response.new(@lookup[nil].terminates, params)
114
90
  end
115
91
  elsif next_part = @lookup[part]
116
92
  next_part.find(request, path, params)
@@ -120,16 +96,14 @@ class Usher
120
96
  next_part.value.valid!(part)
121
97
  case next_part.value.type
122
98
  when :*
123
- params << [next_part.value.name, []]
124
- params.last.last << part
99
+ params << [next_part.value.name, []] unless params.last && params.last.first == next_part.value.name
100
+ params.last.last << part unless part.is_a?(Symbol)
101
+ find(request, path, params)
125
102
  when :':'
126
103
  params << [next_part.value.name, part]
104
+ next_part.find(request, path, params)
127
105
  end
128
106
  end
129
- next_part.find(request, path, params)
130
- elsif has_globber? && p = find_parent{|p| p.value.is_a?(Route::Variable) && p.value.type == :*}
131
- params.last.last << part
132
- find(request, path, params)
133
107
  else
134
108
  nil
135
109
  end
@@ -14,8 +14,9 @@ class Usher
14
14
  end
15
15
 
16
16
  def eql?(o)
17
- o.is_a?(Http) && o.type == type && o.value == value
17
+ o.is_a?(self.class) && o.type == type && o.value == value
18
18
  end
19
+ alias == eql?
19
20
  end
20
21
  end
21
22
  end
@@ -80,9 +80,18 @@ describe "Usher URL generation" do
80
80
  proc {route_set.generate_url(route_set.add_route('/:controller/:action').primary_path, {:controller => 'controller'})}.should raise_error Usher::MissingParameterException
81
81
  end
82
82
 
83
+ it "should generate from a route" do
84
+ route_set.generate_url(route_set.add_route('/:controller/:action'), {:controller => 'controller', :action => 'action'}).should == '/controller/action'
85
+ end
86
+
83
87
  it "should require all the parameters (array) to generate a route" do
84
88
  route_set.add_named_route(:name, '/:controller/:action.:format')
85
89
  proc {route_set.generate_url(:name, ['controller', 'action'])}.should raise_error Usher::MissingParameterException
86
90
  end
87
91
 
92
+ it "should generate a route when only one parameter is given" do
93
+ route_set.add_named_route(:name, '/:controller')
94
+ route_set.generate_url(:name, 'controller').should == '/controller'
95
+ end
96
+
88
97
  end
@@ -19,6 +19,11 @@ describe "Usher grapher" do
19
19
  route_set.generate_url(nil, {:a => 'A', :b => 'B', :c => 'C'}).should == '/A/B/C'
20
20
  end
21
21
 
22
+ it "should fail to generate a route when none matches" do
23
+ route_set.add_route('/:a/:b')
24
+ proc {route_set.generate_url(nil, {:c => 'C', :d => 'D'}) }.should raise_error Usher::UnrecognizedException
25
+ end
26
+
22
27
  it "should find the most specific route and append extra parts on as a query string" do
23
28
  route_set.add_route('/:a/:b/:c')
24
29
  route_set.add_route('/:a/:b')
@@ -36,4 +36,33 @@ describe "Usher route adding" do
36
36
  route_set.add_named_route(:route, '/bad/route', :controller => 'sample').should == route_set.named_routes[:route]
37
37
  end
38
38
 
39
+ it "should calculate depths for nodes" do
40
+ route_set.add_named_route(:route, '/bad/route/three/four')
41
+ route_set.tree.depth.should == 0
42
+ route_set.tree.lookup[:/].depth.should == 1
43
+ end
44
+
45
+ it "should pp for nodes" do
46
+ route_set.add_named_route(:route, '/bad/route/three/four')
47
+ route_set.tree.depth.should == 0
48
+ old_out = $stdout
49
+ $stdout = (output = StringIO.new)
50
+ route_set.tree.lookup[:/].lookup['bad'].lookup[:/].pp
51
+ $stdout = old_out
52
+ output.rewind
53
+ output.read.should == <<-HEREDOC
54
+ 3: :/ false
55
+ route ==>
56
+ 4: "route" false
57
+ / ==>
58
+ 5: :/ false
59
+ three ==>
60
+ 6: "three" false
61
+ / ==>
62
+ 7: :/ false
63
+ four ==>
64
+ 8: "four" true
65
+ HEREDOC
66
+ end
67
+
39
68
  end
@@ -35,6 +35,11 @@ describe "Usher route recognition" do
35
35
  route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:format , 'html']])
36
36
  end
37
37
 
38
+ it "should recognize a glob-style variable" do
39
+ target_route = route_set.add_route('/sample/*format', :controller => 'sample', :action => 'action')
40
+ route_set.recognize(build_request({:method => 'get', :path => '/sample/html/json/apple'})).params.should == [[:format, ['html', 'json', 'apple']]]
41
+ end
42
+
38
43
  it "should recognize a format-style literal" do
39
44
  target_route = route_set.add_route('/:action.html', :controller => 'sample', :action => 'action')
40
45
  route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:action , 'sample']])
@@ -72,11 +77,26 @@ describe "Usher route recognition" do
72
77
  insecure_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com', :user_agent => false})).path.route
73
78
  end
74
79
 
80
+ it "should use conditionals that are arrays" do
81
+ # hijacking user_agent
82
+ www_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['www'], :method => 'get'})
83
+ admin_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['admin'], :method => 'get'})
84
+
85
+ admin_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['admin'], :user_agent => true})).path.route
86
+ www_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['www'], :user_agent => false})).path.route
87
+ end
88
+
75
89
  it "should use a transformer (proc) on incoming variables" do
76
90
  route_set.add_route('/:controller/:action/:id', :transformers => {:id => proc{|v| v.to_i}})
77
91
  route_set.recognize(build_request({:method => 'get', :path => '/products/show/123asd', :domain => 'admin.host.com'})).params.rassoc(123).first.should == :id
78
92
  end
79
93
 
94
+ it "should use a requirement (proc) on incoming variables" do
95
+ route_set.add_route('/:controller/:action/:id', :id => proc{|v| Integer(v)})
96
+ proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com'}))}.should_not raise_error Usher::ValidationException
97
+ proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/123asd', :domain => 'admin.host.com'}))}.should raise_error Usher::ValidationException
98
+ end
99
+
80
100
  it "shouldn't care about mildly weird characters in the URL" do
81
101
  route = route_set.add_route('/!asd,qwe/hjk$qwe/:id')
82
102
  route_set.recognize(build_request({:method => 'get', :path => '/!asd,qwe/hjk$qwe/09AZaz$-_+!*\'', :domain => 'admin.host.com'})).params.rassoc('09AZaz$-_+!*\'').first.should == :id
@@ -0,0 +1,15 @@
1
+ require 'lib/usher'
2
+
3
+ describe "Usher request method" do
4
+
5
+ it "support eql? and ==" do
6
+ Usher::Route::RequestMethod.new(:method, 'blah').should == Usher::Route::RequestMethod.new(:method, 'blah')
7
+ Usher::Route::RequestMethod.new(:method, 'blah').should.eql?(Usher::Route::RequestMethod.new(:method, 'blah'))
8
+ end
9
+
10
+ it "support hash" do
11
+ Usher::Route::RequestMethod.new(:method, 'blah').hash.should == (Usher::Route::RequestMethod.new(:method, 'blah')).hash
12
+ end
13
+
14
+
15
+ end
@@ -53,5 +53,15 @@ describe "Usher route tokenizing" do
53
53
  [:/, "test", :/, "this", :/, "split", '.', Usher::Route::Variable.new(:':', :format)]
54
54
  ]
55
55
  end
56
+
57
+ it "should to_s all different variable types" do
58
+ Usher::Splitter.for_delimiters(['/', '.']).split('/:split/*splitter').first.collect{|v| v.to_s} ==
59
+ [ ':split', '*splitter' ]
60
+ end
61
+
62
+ it "should == variable types" do
63
+ parts = Usher::Splitter.for_delimiters(['/', '.']).split('/:split/:split').first
64
+ parts[1].should == parts[3]
65
+ end
56
66
 
57
67
  end
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.3.2
4
+ version: 0.3.3
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-06 00:00:00 -07:00
12
+ date: 2009-04-07 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,6 +68,7 @@ files:
68
68
  - spec/rails/path_spec.rb
69
69
  - spec/rails/recognize_spec.rb
70
70
  - spec/recognize_spec.rb
71
+ - spec/request_method_spec.rb
71
72
  - spec/spec.opts
72
73
  - spec/split_spec.rb
73
74
  - rails/init.rb