diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/routing')
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 24 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/route_set.rb | 23 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/url_for.rb | 2 |
3 files changed, 39 insertions, 10 deletions
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 4ea3937057..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' @@ -100,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" @@ -245,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 @@ -535,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 @@ -640,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] @@ -848,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 @@ -1509,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/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 57ce7b4ba9..0ae668d42a 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -103,7 +103,7 @@ module ActionDispatch inner_options = args.extract_options! result = options.dup - if args.any? + 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) @@ -188,7 +188,8 @@ module ActionDispatch 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}.merge!(url_options) + options = #{options.inspect} + options.merge!(url_options) if respond_to?(:url_options) options[:path] = "#{optimized_helper(route)}" ActionDispatch::Http::URL.url_for(options) else @@ -202,7 +203,7 @@ module ActionDispatch # 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. @@ -214,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 @@ -456,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 @@ -518,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! diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index d75bb1c2de..ee02f4b531 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -68,7 +68,7 @@ module ActionDispatch # This generates, among other things, the method <tt>users_path</tt>. By default, # this method is accessible from your controllers, views and mailers. If you need # to access this auto-generated method from other places (such as a model), then - # you can do that by including ActionController::UrlFor in your class: + # you can do that by including Rails.application.routes.url_helpers in your class: # # class User < ActiveRecord::Base # include Rails.application.routes.url_helpers |