joshbuddy-usher 0.1.0 → 0.1.1

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
@@ -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