joshbuddy-usher 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -7,7 +7,6 @@ begin
7
7
  s.description = s.summary = "A general purpose routing library"
8
8
  s.email = "joshbuddy@gmail.com"
9
9
  s.homepage = "http://github.com/joshbuddy/usher"
10
- s.description = "TODO"
11
10
  s.authors = ["Joshua Hull"]
12
11
  s.files = FileList["[A-Z]*", "{lib,spec,rails}/**/*"]
13
12
  s.add_dependency 'joshbuddy-fuzzy_hash'
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 1
4
- :patch: 0
4
+ :patch: 1
data/lib/usher.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
- require 'strscan'
4
- require 'set'
5
3
  require 'usher/node'
6
4
  require 'usher/route'
7
5
  require 'usher/grapher'
@@ -12,15 +10,24 @@ class Usher
12
10
  attr_reader :tree, :named_routes, :route_count, :routes
13
11
 
14
12
  SymbolArraySorter = proc {|a,b| a.hash <=> b.hash}
15
-
13
+
14
+ # Returns whether the route set is empty
15
+ #
16
+ # set = Usher.new
17
+ # set.empty? => true
18
+ # set.add_route('/test')
19
+ # set.empty? => false
16
20
  def empty?
17
21
  @route_count.zero?
18
22
  end
19
23
 
20
- def lookup
21
- @tree.lookup
22
- end
23
-
24
+ # Resets the route set back to its initial state
25
+ #
26
+ # set = Usher.new
27
+ # set.add_route('/test')
28
+ # set.empty? => false
29
+ # set.reset!
30
+ # set.empty? => true
24
31
  def reset!
25
32
  @tree = Node.root(self)
26
33
  @named_routes = {}
@@ -30,19 +37,60 @@ class Usher
30
37
  end
31
38
  alias clear! reset!
32
39
 
33
- def initialize(mode = :rails)
34
- @mode = mode
40
+ # Creates a route set
41
+ def initialize
35
42
  reset!
36
43
  end
37
44
 
45
+ # Adds a route referencable by +name+. Sett add_route for format +path+ and +options+.
46
+ #
47
+ # set = Usher.new
48
+ # set.add_named_route(:test_route, '/test')
38
49
  def add_named_route(name, path, options = {})
39
50
  add_route(path, options).name(name)
40
51
  end
41
52
 
53
+ # Attaches a +route+ to a +name+
54
+ #
55
+ # set = Usher.new
56
+ # route = set.add_route('/test')
57
+ # set.name(:test, route)
42
58
  def name(name, route)
43
59
  @named_routes[name] = route.primary_path
44
60
  end
45
61
 
62
+ # Creates a route from +path+ and +options+
63
+ #
64
+ # <tt>+path+</tt>::
65
+ # A path consists a mix of dynamic and static parts delimited by <tt>/</tt>
66
+ #
67
+ # *Dynamic*
68
+ #
69
+ # Dynamic parts are prefixed with either :, *. :variable matches only one part of the path, whereas *variable can match one or
70
+ # more parts. Example:
71
+ # <b>/path/:variable/path</b> would match
72
+ #
73
+ # * /path/test/path
74
+ # * /path/something_else/path
75
+ # * /path/one_more/path
76
+ #
77
+ # In the above examples, 'test', 'something_else' and 'one_more' respectively would be bound to the key :variable.
78
+ # However, /path/test/one_more/path would not be matched.
79
+ #
80
+ # Example:
81
+ # <b>/path/*variable/path</b> would match
82
+ #
83
+ # * /path/one/two/three/path
84
+ # * /path/four/five/path
85
+ #
86
+ # In the above examples, ['one', 'two', 'three'] and ['four', 'five'] respectively would be bound to the key :variable.
87
+ #
88
+ # <tt>+options+</tt>::
89
+ # --
90
+ # * :transformers - Transforms a variable before it gets to the conditions and 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.
91
+ # * :requirements - After transformation, tests the condition using ===. If it returns false, it raises an +Usher::ValidationException+
92
+ # * :conditions - Accepts any of the following +:protocol+, +:domain+, +:port+, +:query_string+, +:remote_ip+, +:user_agent+, +:referer+ and +:method+. This can be either a +string+ or a +regexp+.
93
+ #
46
94
  def add_route(path, options = {})
47
95
  transformers = options.delete(:transformers) || {}
48
96
  conditions = options.delete(:conditions) || {}
@@ -63,6 +111,11 @@ class Usher
63
111
  route
64
112
  end
65
113
 
114
+ # Recognizes a +request+ and returns +nil+ or an Usher::Route::Path
115
+ #
116
+ # set = Usher.new
117
+ # route = set.add_route('/test')
118
+ # set.name(:test, route)
66
119
  def recognize(request)
67
120
  @tree.find(request)
68
121
  end
@@ -1,4 +1,4 @@
1
1
  class Usher
2
- class UnrecognizedException < RuntimeError
3
- end
2
+ class UnrecognizedException < RuntimeError; end
3
+ class ValidationException < RuntimeError; end
4
4
  end
data/lib/usher/node.rb CHANGED
@@ -127,7 +127,7 @@ class Usher
127
127
  when Symbol
128
128
  part = part.send(t)
129
129
  end
130
- raise "#{part} does not conform to #{next_part.value.validator}" if next_part.value.validator && (not next_part.value.validator === part)
130
+ raise ValidationException.new("#{part} does not conform to #{next_part.value.validator}") if next_part.value.validator && (not next_part.value.validator === part)
131
131
  case next_part.value.type
132
132
  when :*
133
133
  params << [next_part.value.name, []]
@@ -2,7 +2,7 @@ class Usher
2
2
  class Route
3
3
  class Splitter
4
4
 
5
- ScanRegex = /((:|\*||\.:|)[0-9a-z_]+|\/|\(|\))/
5
+ ScanRegex = /((:|\*||\.:|\.)[0-9a-z_]+|\/|\(|\))/
6
6
  UrlScanRegex = /\/|\.?\w+/
7
7
 
8
8
  attr_reader :paths
@@ -30,6 +30,21 @@ describe "Usher route recognition" do
30
30
  target_route.paths.include?(route_set.recognize(build_request({:method => 'get', :path => '/sample', :domain => 'admin.host.com'})).first).should == true
31
31
  end
32
32
 
33
+ it "should recognize a format-style variable" do
34
+ target_route = route_set.add_route('/sample.:format', :controller => 'sample', :action => 'action')
35
+ route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == [target_route.paths.first, [[:format , 'html']]]
36
+ end
37
+
38
+ it "should recognize a format-style literal" do
39
+ target_route = route_set.add_route(':action.html', :controller => 'sample', :action => 'action')
40
+ route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == [target_route.paths.first, [[:action , 'sample']]]
41
+ end
42
+
43
+ it "should recognize a format-style variable along side another variable" do
44
+ target_route = route_set.add_route(':action.:format', :controller => 'sample', :action => 'action')
45
+ route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == [target_route.paths.first, [[:action , 'sample'], [:format, 'html']]]
46
+ end
47
+
33
48
  it "should recognize a specific route when several http-style restrictions are used" do
34
49
  target_route_http_admin = route_set.add_route('/sample', :controller => 'sample', :action => 'action', :conditions => {:protocol => 'http', :domain => 'admin.spec.com'})
35
50
  target_route_http_www = route_set.add_route('/sample', :controller => 'sample', :action => 'action', :conditions => {:protocol => 'http', :domain => 'www.spec.com'})
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.1.0
4
+ version: 0.1.1
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-03-26 00:00:00 -07:00
12
+ date: 2009-03-27 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,7 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- description: TODO
25
+ description: A general purpose routing library
26
26
  email: joshbuddy@gmail.com
27
27
  executables: []
28
28