lib/usher/node.rb in joshbuddy-usher-0.4.8 vs lib/usher/node.rb in joshbuddy-usher-0.4.10
- old
+ new
@@ -4,28 +4,37 @@
class Node
Response = Struct.new(:path, :params)
- attr_reader :lookup
+ attr_reader :lookup, :greedy_lookup
attr_accessor :terminates, :exclusive_type, :parent, :value, :request_methods, :globs_capture_separators
def initialize(parent, value)
@parent = parent
@value = value
@lookup = Hash.new
+ @greedy_lookup = Hash.new
@exclusive_type = nil
end
def upgrade_lookup
@lookup = FuzzyHash.new(@lookup)
end
+ def upgrade_greedy_lookup
+ @greedy_lookup = FuzzyHash.new(@greedy_lookup)
+ end
+
def depth
@depth ||= @parent && @parent.is_a?(Node) ? @parent.depth + 1 : 0
end
+ def greedy?
+ !@greedy_lookup.empty?
+ end
+
def self.root(route_set, request_methods, globs_capture_separators)
root = self.new(route_set, nil)
root.request_methods = request_methods
root.globs_capture_separators = globs_capture_separators
root
@@ -67,51 +76,73 @@
parts.unshift(key)
current_node.lookup[nil] ||= Node.new(current_node, Route::RequestMethod.new(current_node.exclusive_type, nil))
end
else
key.globs_capture_separators = globs_capture_separators if key.is_a?(Route::Variable)
-
- if !key.is_a?(Route::Variable)
+
+ case key
+ when Route::Variable
+ if key.greedy?
+ if key.regex_matcher
+ current_node.upgrade_greedy_lookup
+ current_node.greedy_lookup[key.regex_matcher] ||= Node.new(current_node, key)
+ else
+ current_node.greedy_lookup[nil] ||= Node.new(current_node, key)
+ end
+ else
+ if key.regex_matcher
+ current_node.upgrade_lookup
+ current_node.lookup[key.regex_matcher] ||= Node.new(current_node, key)
+ else
+ current_node.lookup[nil] ||= Node.new(current_node, key)
+ end
+ end
+ else
current_node.upgrade_lookup if key.is_a?(Regexp)
current_node.lookup[key] ||= Node.new(current_node, key)
- elsif key.regex_matcher
- current_node.upgrade_lookup
- current_node.lookup[key.regex_matcher] ||= Node.new(current_node, key)
- else
- current_node.lookup[nil] ||= Node.new(current_node, key)
- end
+ end
+
end
current_node = target_node
end
current_node.terminates = path
end
route
end
- def find(usher, request, path, params = [])
+ def find(usher, request, original_path, path, params = [], position = 0)
if exclusive_type
[lookup[request.send(exclusive_type)], lookup[nil]].each do |n|
- if n && (ret = n.find(usher, request, path.dup, params.dup))
+ if n && (ret = n.find(usher, request, original_path, path.dup, params.dup, position))
return ret
end
end
elsif path.size.zero? && terminates?
Response.new(terminates, params)
+ elsif !path.size.zero? && (greedy? && ((next_path, matched_part) = greedy_lookup.match_with_result(whole_path = original_path[position, original_path.size])))
+ position += matched_part.size
+ params << [next_path.value.name, whole_path.slice!(0, matched_part.size)]
+ next_path.find(usher, request, original_path, whole_path.size.zero? ? whole_path : usher.splitter.url_split(whole_path), params, position)
elsif !path.size.zero? && (next_part = lookup[part = path.shift] || lookup[nil])
+ position += part.size
case next_part.value
when Route::Variable
case next_part.value.type
when :*
params << [next_part.value.name, []] unless params.last && params.last.first == next_part.value.name
loop do
- if (next_part.value.look_ahead === part || (!usher.splitter.delimiter_chars.include?(part[0]) && next_part.value.regex_matcher && !next_part.value.regex_matcher.match(part)))
+ if (next_part.value.look_ahead === part || (!usher.delimiter_chars.include?(part[0]) && next_part.value.regex_matcher && !next_part.value.regex_matcher.match(part)))
path.unshift(part)
- path.unshift(next_part.parent.value) if usher.splitter.delimiter_chars.include?(next_part.parent.value[0])
+ position -= part.size
+ if usher.delimiter_chars.include?(next_part.parent.value[0])
+ path.unshift(next_part.parent.value)
+ position -= next_part.parent.value.size
+ end
break
elsif next_part.value.globs_capture_separators
params.last.last << part
- elsif !usher.splitter.delimiter_chars.include?(part[0])
+ elsif !usher.delimiter_chars.include?(part[0])
next_part.value.valid!(part)
params.last.last << part
end
if path.size.zero?
break
@@ -122,14 +153,16 @@
when :':'
var = next_part.value
var.valid!(part)
params << [var.name, part]
until (var.look_ahead === path.first) || path.empty?
- params.last.last << path.shift
+ next_path_part = path.shift
+ position += next_path_part.size
+ params.last.last << next_path_part
end
end
end
- next_part.find(usher, request, path, params)
+ next_part.find(usher, request, original_path, path, params, position)
else
nil
end
end