usher 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.rdoc ADDED
@@ -0,0 +1,9 @@
1
+ = Changelog
2
+
3
+ == From 0.6.5 to 0.6.6
4
+
5
+ * Faster recognition (~10%)
6
+ * Nicer exception message when generating a route and raising a MissingParameterException
7
+ * Nodes now support #ancestors and #root methods.
8
+ * Cache responses on non-dynamic paths.
9
+ * Started a changelog.
data/VERSION.yml CHANGED
@@ -2,4 +2,4 @@
2
2
  :build:
3
3
  :major: 0
4
4
  :minor: 6
5
- :patch: 5
5
+ :patch: 6
@@ -3,7 +3,7 @@ class Usher
3
3
  class Response < Struct.new(:path, :params_as_array, :remaining_path, :matched_path)
4
4
 
5
5
  def params
6
- @params ||= params_as_array.nil? ? [] : path.convert_params_array(params_as_array)
6
+ @params ||= path.convert_params_array(params_as_array)
7
7
  end
8
8
 
9
9
  def partial_match?
@@ -11,7 +11,7 @@ class Usher
11
11
  end
12
12
 
13
13
  def params_as_hash
14
- @params_as_hash ||= params_as_array.nil? ? {} : params_as_array.inject({}){|hash, val| hash[path.dynamic_keys[hash.size]] = val; hash}
14
+ @params_as_hash ||= params_as_array.inject({}){|hash, val| hash[path.dynamic_keys[hash.size]] = val; hash}
15
15
  end
16
16
 
17
17
  def destination
@@ -7,6 +7,10 @@ class Usher
7
7
  self.request_methods = request_methods
8
8
  end
9
9
 
10
+ def route_set
11
+ parent
12
+ end
13
+
10
14
  def add(route)
11
15
  route.paths.each do |path|
12
16
  set_path_with_destination(path)
data/lib/usher/node.rb CHANGED
@@ -52,6 +52,26 @@ class Usher
52
52
  @terminates && @terminates.route.recognizable?
53
53
  end
54
54
 
55
+ def ancestors
56
+ unless @ancestors
57
+ @ancestors = []
58
+ node = self
59
+ while (node.respond_to?(:parent))
60
+ @ancestors << node
61
+ node = node.parent
62
+ end
63
+ end
64
+ @ancestors
65
+ end
66
+
67
+ def root
68
+ @root ||= ancestors.last
69
+ end
70
+
71
+ def route_set
72
+ @route_set ||= root.route_set
73
+ end
74
+
55
75
  def pp
56
76
  $stdout << " " * depth
57
77
  $stdout << "#{terminates? ? '* ' : ''}#{depth}: #{value.inspect}\n"
@@ -72,68 +92,71 @@ class Usher
72
92
  end if request
73
93
  end
74
94
 
75
- def find(usher, request_object, original_path, path, params = nil, position = 0)
76
- if terminates? && (path.empty? || terminates.route.partial_match? || (usher.ignore_trailing_delimiters? && path.all?{|p| usher.delimiters.include?(p)}))
77
- terminates.route.partial_match? ?
78
- Response.new(terminates, params, original_path[position, original_path.size], original_path[0, position]) :
79
- Response.new(terminates, params, nil, original_path)
80
- elsif !path.empty? and greedy and match_with_result_output = greedy.match_with_result(whole_path = original_path[position, original_path.size])
95
+ def find(request_object, original_path, path, params = [])
96
+ # terminates or is partial
97
+ if terminates? && (path.empty? || terminates.route.partial_match? || (route_set.ignore_trailing_delimiters? && path.all?{|p| route_set.delimiters.include?(p)}))
98
+ if terminates.cached_response
99
+ terminates.cached_response
100
+ else
101
+ terminates.route.partial_match? ?
102
+ Response.new(terminates, params, path.join, original_path[0, original_path.size - path.join.size]) :
103
+ Response.new(terminates, params, nil, original_path)
104
+ end
105
+ # terminates or is partial
106
+ elsif !path.empty? and greedy and match_with_result_output = greedy.match_with_result(whole_path = path.join)
81
107
  next_path, matched_part = match_with_result_output
82
- position += matched_part.size
83
108
  whole_path.slice!(0, matched_part.size)
84
- (params ||= []) << matched_part if next_path.value.is_a?(Route::Variable)
85
- next_path.find(usher, request_object, original_path, whole_path.empty? ? whole_path : usher.splitter.split(whole_path), params, position)
109
+ params << matched_part if next_path.value.is_a?(Route::Variable)
110
+ next_path.find(request_object, original_path, whole_path.empty? ? whole_path : route_set.splitter.split(whole_path), params)
86
111
  elsif !path.empty? and normal and next_part = normal[path.first] || normal[nil]
87
112
  part = path.shift
88
- position += part.size
89
113
  case next_part.value
90
- when String
91
- # do nothing
92
- when Route::Variable::Single
93
- # get the variable
94
- var = next_part.value
95
- # do a validity check
96
- var.valid!(part)
97
- # because its a variable, we need to add it to the params array
98
- (params ||= []) << part
99
- until path.empty? || (var.look_ahead === path.first) # variables have a look ahead notion,
114
+ when String
115
+ when Route::Variable::Single
116
+ # get the variable
117
+ variable = next_part.value
118
+ # do a validity check
119
+ variable.valid!(part)
120
+ # because its a variable, we need to add it to the params array
121
+ parameter_value = part
122
+ if variable.look_ahead
123
+ until path.empty? || (variable.look_ahead === path.first) # variables have a look ahead notion,
100
124
  next_path_part = path.shift # and until they are satified,
101
- position += next_path_part.size # keep appending to the value in params
102
- params.last << next_path_part
103
- end if var.look_ahead && usher.delimiters.size > 1
104
- when Route::Variable::Glob
105
- (params ||= []) << []
106
- while true
107
- if (next_part.value.look_ahead === part || (!usher.delimiters.unescaped.include?(part) && next_part.value.regex_matcher && !next_part.value.regex_matcher.match(part)))
108
- path.unshift(part)
109
- position -= part.size
110
- if usher.delimiters.unescaped.include?(next_part.parent.value)
111
- path.unshift(next_part.parent.value)
112
- position -= next_part.parent.value.size
113
- end
114
- break
115
- elsif !usher.delimiters.unescaped.include?(part)
116
- next_part.value.valid!(part)
117
- params.last << part
118
- end
119
- if path.empty?
120
- break
121
- else
122
- part = path.shift
125
+ parameter_value << next_path_part
126
+ end
127
+ end
128
+ params << parameter_value
129
+ when Route::Variable::Glob
130
+ params << []
131
+ loop do
132
+ if (next_part.value.look_ahead === part || (!route_set.delimiters.unescaped.include?(part) && next_part.value.regex_matcher && !next_part.value.regex_matcher.match(part)))
133
+ path.unshift(part)
134
+ if route_set.delimiters.unescaped.include?(next_part.parent.value)
135
+ path.unshift(next_part.parent.value)
123
136
  end
137
+ break
138
+ elsif !route_set.delimiters.unescaped.include?(part)
139
+ next_part.value.valid!(part)
140
+ params.last << part
141
+ end
142
+ if path.empty?
143
+ break
144
+ else
145
+ part = path.shift
124
146
  end
147
+ end
125
148
  end
126
- next_part.find(usher, request_object, original_path, path, params, position)
149
+ next_part.find(request_object, original_path, path, params)
127
150
  elsif request_method_type
128
- return_value = if (specific_node = request[request_object.send(request_method_type)] and ret = specific_node.find(usher, request_object, original_path, path.dup, params && params.dup, position))
129
- usher.priority_lookups? ? [ret] : ret
151
+ return_value = if (specific_node = request[request_object.send(request_method_type)] and ret = specific_node.find(request_object, original_path, path.dup, params && params.dup))
152
+ route_set.priority_lookups? ? [ret] : ret
130
153
  end
131
154
 
132
- if usher.priority_lookups? || return_value.nil? and general_node = request[nil] and ret = general_node.find(usher, request_object, original_path, path.dup, params && params.dup, position)
133
- return_value = usher.priority_lookups? && return_value ? [return_value, ret] : ret
155
+ if route_set.priority_lookups? || return_value.nil? and general_node = request[nil] and ret = general_node.find(request_object, original_path, path.dup, params && params.dup)
156
+ return_value = route_set.priority_lookups? && return_value ? [return_value, ret] : ret
134
157
  end
135
158
 
136
- unless usher.priority_lookups?
159
+ unless route_set.priority_lookups?
137
160
  return_value
138
161
  else
139
162
  return_value = Array(return_value).flatten.compact
@@ -2,7 +2,7 @@ class Usher
2
2
  class Route
3
3
  class Path
4
4
 
5
- attr_accessor :route
5
+ attr_accessor :route, :cached_response
6
6
  attr_reader :parts
7
7
 
8
8
  def initialize(route, parts)
@@ -21,14 +21,14 @@ class Usher
21
21
  when String
22
22
  result << part
23
23
  when Route::Variable::Glob
24
- value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new)
24
+ value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new("expected a value for #{part.name}"))
25
25
  value.each_with_index do |current_value, index|
26
26
  part.valid!(current_value)
27
27
  result << current_value.to_s
28
28
  result << usher.delimiters.first if index != value.size - 1
29
29
  end
30
30
  when Route::Variable
31
- value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new)
31
+ value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new("expected a value for #{part.name}"))
32
32
  part.valid!(value)
33
33
  result << value.to_s
34
34
  end
@@ -123,9 +123,9 @@ class Usher
123
123
  if variable
124
124
  variable_type = variable.slice!(0).chr.to_sym
125
125
  variable_class = case variable_type
126
- when :'!' : Usher::Route::Variable::Greedy
127
- when :* : Usher::Route::Variable::Glob
128
- when :':' : Usher::Route::Variable::Single
126
+ when :'!' then Usher::Route::Variable::Greedy
127
+ when :* then Usher::Route::Variable::Glob
128
+ when :':' then Usher::Route::Variable::Single
129
129
  end
130
130
  variable_name = variable[0, variable.size - 1].to_sym
131
131
  current_group << variable_class.new(variable_name, regex, requirements && requirements[variable_name])
data/lib/usher.rb CHANGED
@@ -232,7 +232,11 @@ class Usher
232
232
  # route = set.add_route('/test')
233
233
  # set.recognize(Request.new('/test')).path.route == route => true
234
234
  def recognize(request, path = request.path)
235
- @root.find(self, request, path, @splitter.split(path))
235
+ response = @root.find(request, path, @splitter.split(path))
236
+ if response && !response.path.dynamic?
237
+ response.path.cached_response = response
238
+ end
239
+ response
236
240
  end
237
241
 
238
242
  # Recognizes a +path+ and returns +nil+ or an Usher::Node::Response, which is a struct containing a Usher::Route::Path and an array of arrays containing the extracted parameters. Convenience method for when recognizing on the request object is unneeded.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Neighman
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-01-13 00:00:00 -05:00
17
+ date: 2010-01-15 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -36,6 +36,7 @@ extensions: []
36
36
  extra_rdoc_files:
37
37
  - README.rdoc
38
38
  files:
39
+ - CHANGES.rdoc
39
40
  - History.txt
40
41
  - Manifest.txt
41
42
  - README.rdoc