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.rb125
1 files changed, 125 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..3b609a184d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -0,0 +1,125 @@
+module ActionDispatch
+ module Journey # :nodoc:
+ class Route # :nodoc:
+ attr_reader :app, :path, :defaults, :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 = {})
+ @name = name
+ @app = app
+ @path = path
+
+ @constraints = constraints
+ @defaults = defaults
+ @required_defaults = nil
+ @required_parts = nil
+ @parts = nil
+ @decorated_ast = nil
+ @precedence = 0
+ @path_formatter = @path.build_formatter
+ end
+
+ def ast
+ @decorated_ast ||= begin
+ decorated_ast = path.ast
+ decorated_ast.grep(Nodes::Terminal).each { |n| n.memo = self }
+ decorated_ast
+ end
+ 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
+ required_parts + 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(&:to_sym)
+ end
+ alias :segment_keys :parts
+
+ def format(path_options)
+ @path_formatter.evaluate path_options
+ end
+
+ def optional_parts
+ path.optional_names.map(&:to_sym)
+ end
+
+ def required_parts
+ @required_parts ||= path.required_names.map(&:to_sym)
+ end
+
+ def required_default?(key)
+ (constraints[:required_defaults] || []).include?(key)
+ end
+
+ def required_defaults
+ @required_defaults ||= @defaults.dup.delete_if do |k,_|
+ parts.include?(k) || !required_default?(k)
+ end
+ end
+
+ def glob?
+ !path.spec.grep(Nodes::Star).empty?
+ end
+
+ def dispatcher?
+ @app.dispatcher?
+ end
+
+ def matches?(request)
+ constraints.all? do |method, value|
+ next true unless request.respond_to?(method)
+
+ case value
+ when Regexp, String
+ value === request.send(method).to_s
+ when Array
+ value.include?(request.send(method))
+ when TrueClass
+ request.send(method).present?
+ when FalseClass
+ request.send(method).blank?
+ else
+ value === request.send(method)
+ end
+ end
+ end
+
+ def ip
+ constraints[:ip] || //
+ end
+
+ def verb
+ constraints[:request_method] || //
+ end
+ end
+ end
+end