aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/routing
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/routing')
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb26
-rw-r--r--actionpack/lib/action_dispatch/routing/redirection.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb80
3 files changed, 55 insertions, 54 deletions
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 1a1a054985..7a22b65c44 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/reverse_merge'
+require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/enumerable'
require 'active_support/inflector'
@@ -35,6 +36,8 @@ module ActionDispatch
}
return true
+ ensure
+ req.reset_parameters
end
def call(env)
@@ -98,6 +101,10 @@ module ActionDispatch
raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
end
end
+
+ if @options[:constraints].is_a?(Hash)
+ (@options[:defaults] ||= {}).reverse_merge!(defaults_from_constraints(@options[:constraints]))
+ end
end
# match "account/overview"
@@ -243,6 +250,11 @@ module ActionDispatch
def default_action
@options[:action] || @scope[:action]
end
+
+ def defaults_from_constraints(constraints)
+ url_keys = [:protocol, :subdomain, :domain, :host, :port]
+ constraints.slice(*url_keys).select{ |k, v| v.is_a?(String) || v.is_a?(Fixnum) }
+ end
end
# Invokes Rack::Mount::Utils.normalize path and ensure that
@@ -533,7 +545,8 @@ module ActionDispatch
private
def map_method(method, args, &block)
options = args.extract_options!
- options[:via] = method
+ options[:via] = method
+ options[:path] ||= args.first if args.first.is_a?(String)
match(*args, options, &block)
self
end
@@ -638,6 +651,10 @@ module ActionDispatch
block, options[:constraints] = options[:constraints], {}
end
+ if options[:constraints].is_a?(Hash)
+ (options[:defaults] ||= {}).reverse_merge!(defaults_from_constraints(options[:constraints]))
+ end
+
scope_options.each do |option|
if value = options.delete(option)
recover[option] = @scope[option]
@@ -846,6 +863,11 @@ module ActionDispatch
def override_keys(child) #:nodoc:
child.key?(:only) || child.key?(:except) ? [:only, :except] : []
end
+
+ def defaults_from_constraints(constraints)
+ url_keys = [:protocol, :subdomain, :domain, :host, :port]
+ constraints.slice(*url_keys).select{ |k, v| v.is_a?(String) || v.is_a?(Fixnum) }
+ end
end
# Resource routing allows you to quickly declare all of the common routes
@@ -1507,7 +1529,7 @@ module ActionDispatch
prefix = shallow_scoping? ?
"#{@scope[:shallow_path]}/#{parent_resource.path}/:id" : @scope[:path]
- path = if canonical_action?(action, path.blank?)
+ if canonical_action?(action, path.blank?)
prefix.to_s
else
"#{prefix}/#{action_path(action, path)}"
diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb
index 444a79c50d..95c588c00a 100644
--- a/actionpack/lib/action_dispatch/routing/redirection.rb
+++ b/actionpack/lib/action_dispatch/routing/redirection.rb
@@ -1,5 +1,6 @@
require 'action_dispatch/http/request'
require 'active_support/core_ext/uri'
+require 'active_support/core_ext/array/extract_options'
require 'rack/utils'
module ActionDispatch
@@ -99,7 +100,7 @@ module ActionDispatch
# match 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
#
def redirect(*args, &block)
- options = args.last.is_a?(Hash) ? args.pop : {}
+ options = args.extract_options!
status = options.delete(:status) || 301
return OptionRedirect.new(status, options) if options.any?
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 7a7810a95c..0ae668d42a 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -99,12 +99,12 @@ module ActionDispatch
@module = Module.new do
protected
- def handle_positional_args(args, options, route)
+ def handle_positional_args(args, options, segment_keys)
inner_options = args.extract_options!
result = options.dup
- if args.any?
- keys = route.segment_keys
+ if args.size > 0
+ keys = segment_keys
if args.size < keys.size - 1 # take format into account
keys -= self.url_options.keys if self.respond_to?(:url_options)
keys -= options.keys
@@ -161,34 +161,13 @@ module ActionDispatch
end
end
- def hash_access_name(name, only_path)
- if only_path
- :"hash_for_#{name}_path"
- else
- :"hash_for_#{name}_url"
- end
- end
-
def define_named_route_methods(name, route)
[true, false].each do |only_path|
hash = route.defaults.merge(:use_route => name, :only_path => only_path)
- define_hash_access route, name, hash
define_url_helper route, name, hash
end
end
- def define_hash_access(route, name, options)
- selector = hash_access_name(name, options[:only_path])
-
- @module.module_eval do
- redefine_method(selector) do |*args|
- self.handle_positional_args(args, options, route)
- end
- protected selector
- end
- helpers << selector
- end
-
# Create a url helper allowing ordered parameters to be associated
# with corresponding dynamic segments, so you can do:
#
@@ -204,36 +183,27 @@ module ActionDispatch
#
def define_url_helper(route, name, options)
selector = url_helper_name(name, options[:only_path])
- hash_access_method = hash_access_name(name, options[:only_path])
-
- if optimize_helper?(route)
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- remove_possible_method :#{selector}
- def #{selector}(*args)
- if args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
- options = #{options.inspect}.merge!(url_options)
- options[:path] = "#{optimized_helper(route)}"
- ActionDispatch::Http::URL.url_for(options)
- else
- url_for(#{hash_access_method}(*args))
- end
- end
- END_EVAL
- else
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- remove_possible_method :#{selector}
- def #{selector}(*args)
- url_for(#{hash_access_method}(*args))
+
+ @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
+ remove_possible_method :#{selector}
+ def #{selector}(*args)
+ if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
+ options = #{options.inspect}
+ options.merge!(url_options) if respond_to?(:url_options)
+ options[:path] = "#{optimized_helper(route)}"
+ ActionDispatch::Http::URL.url_for(options)
+ else
+ url_for(handle_positional_args(args, #{options.inspect}, #{route.segment_keys.inspect}))
end
- END_EVAL
- end
+ end
+ END_EVAL
helpers << selector
end
# Clause check about when we need to generate an optimized helper.
def optimize_helper?(route) #:nodoc:
- route.ast.grep(Journey::Nodes::Star).empty? && route.requirements.except(:controller, :action).empty?
+ route.requirements.except(:controller, :action).empty?
end
# Generates the interpolation to be used in the optimized helper.
@@ -245,7 +215,10 @@ module ActionDispatch
end
route.required_parts.each_with_index do |part, i|
- string_route.gsub!(part.inspect, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
+ # Replace each route parameter
+ # e.g. :id for regular parameter or *path for globbing
+ # with ruby string interpolation code
+ string_route.gsub!(/(\*|:)#{part}/, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
end
string_route
@@ -487,12 +460,12 @@ module ActionDispatch
normalize_options!
normalize_controller_action_id!
use_relative_controller!
- controller.sub!(%r{^/}, '') if controller
+ normalize_controller!
handle_nil_action!
end
def controller
- @controller ||= @options[:controller]
+ @options[:controller]
end
def current_controller
@@ -549,10 +522,15 @@ module ActionDispatch
old_parts = current_controller.split('/')
size = controller.count("/") + 1
parts = old_parts[0...-size] << controller
- @controller = @options[:controller] = parts.join("/")
+ @options[:controller] = parts.join("/")
end
end
+ # Remove leading slashes from controllers
+ def normalize_controller!
+ @options[:controller] = controller.sub(%r{^/}, '') if controller
+ end
+
# This handles the case of :action => nil being explicitly passed.
# It is identical to :action => "index"
def handle_nil_action!