aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/journey/route.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/journey/route.rb')
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb94
1 files changed, 94 insertions, 0 deletions
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
new file mode 100644
index 0000000000..04d31cb580
--- /dev/null
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -0,0 +1,94 @@
+module ActionDispatch
+ module Journey
+ class Route
+ attr_reader :app, :path, :verb, :defaults, :ip, :name
+
+ attr_reader :constraints
+ alias :conditions :constraints
+
+ attr_accessor :precedence
+
+ ##
+ # +path+ is a path constraint.
+ # +constraints+ is a hash of constraints to be applied to this route.
+ def initialize name, app, path, constraints, defaults = {}
+ constraints = constraints.dup
+ @name = name
+ @app = app
+ @path = path
+ @verb = constraints[:request_method] || //
+ @ip = constraints.delete(:ip) || //
+
+ @constraints = constraints
+ @constraints.keep_if { |_,v| Regexp === v || String === v }
+ @defaults = defaults
+ @required_defaults = nil
+ @required_parts = nil
+ @parts = nil
+ @decorated_ast = nil
+ @precedence = 0
+ end
+
+ def ast
+ return @decorated_ast if @decorated_ast
+
+ @decorated_ast = path.ast
+ @decorated_ast.grep(Nodes::Terminal).each { |n| n.memo = self }
+ @decorated_ast
+ end
+
+ def requirements # :nodoc:
+ # needed for rails `rake routes`
+ path.requirements.merge(@defaults).delete_if { |_,v|
+ /.+?/ == v
+ }
+ end
+
+ def segments
+ @path.names
+ end
+
+ def required_keys
+ path.required_names.map { |x| x.to_sym } + required_defaults.keys
+ end
+
+ def score constraints
+ required_keys = path.required_names
+ supplied_keys = constraints.map { |k,v| v && k.to_s }.compact
+
+ return -1 unless (required_keys - supplied_keys).empty?
+
+ score = (supplied_keys & path.names).length
+ score + (required_defaults.length * 2)
+ end
+
+ def parts
+ @parts ||= segments.map { |n| n.to_sym }
+ end
+ alias :segment_keys :parts
+
+ def format path_options
+ path_options.delete_if do |key, value|
+ value.to_s == defaults[key].to_s && !required_parts.include?(key)
+ end
+
+ Visitors::Formatter.new(path_options).accept(path.spec)
+ end
+
+ def optional_parts
+ path.optional_names.map { |n| n.to_sym }
+ end
+
+ def required_parts
+ @required_parts ||= path.required_names.map { |n| n.to_sym }
+ end
+
+ def required_defaults
+ @required_defaults ||= begin
+ matches = parts
+ @defaults.dup.delete_if { |k,_| matches.include? k }
+ end
+ end
+ end
+ end
+end