From fef6c32afe2276dffa0347e25808a86e7a101af1 Mon Sep 17 00:00:00 2001 From: Aaron Batalion Date: Mon, 24 Nov 2008 02:24:19 -0500 Subject: Added optimal formatted routes to rails, deprecating the formatted_* methods, and reducing routes creation by 50% [#1359 state:committed] Signed-off-by: David Heinemeier Hansson --- actionpack/lib/action_controller/resources.rb | 4 +-- .../lib/action_controller/routing/builder.rb | 2 ++ .../lib/action_controller/routing/optimisations.rb | 2 +- actionpack/lib/action_controller/routing/route.rb | 5 ++++ .../lib/action_controller/routing/route_set.rb | 10 ++++++- .../lib/action_controller/routing/segments.rb | 31 ++++++++++++++++++++++ 6 files changed, 49 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index c170528af1..b6cfe2dd68 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -639,10 +639,8 @@ module ActionController formatted_route_path = "#{route_path}.:format" if route_name && @set.named_routes[route_name.to_sym].nil? - map.named_route(route_name, route_path, action_options) - map.named_route("formatted_#{route_name}", formatted_route_path, action_options) + map.named_route(route_name, formatted_route_path, action_options) else - map.connect(route_path, action_options) map.connect(formatted_route_path, action_options) end end diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb index d4e501e780..44d759444a 100644 --- a/actionpack/lib/action_controller/routing/builder.rb +++ b/actionpack/lib/action_controller/routing/builder.rb @@ -34,6 +34,8 @@ module ActionController def segment_for(string) segment = case string + when /\A\.(:format)?\// + OptionalFormatSegment.new when /\A:(\w+)/ key = $1.to_sym key == :controller ? ControllerSegment.new(key) : DynamicSegment.new(key) diff --git a/actionpack/lib/action_controller/routing/optimisations.rb b/actionpack/lib/action_controller/routing/optimisations.rb index 4522ebcb1a..714cf97861 100644 --- a/actionpack/lib/action_controller/routing/optimisations.rb +++ b/actionpack/lib/action_controller/routing/optimisations.rb @@ -65,7 +65,7 @@ module ActionController # rather than triggering the expensive logic in +url_for+. class PositionalArguments < Optimiser def guard_conditions - number_of_arguments = route.segment_keys.size + number_of_arguments = route.required_segment_keys.size # if they're using foo_url(:id=>2) it's one # argument, but we don't want to generate /foos/id2 if number_of_arguments == 1 diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb index a610ec7e84..e4dfdb1718 100644 --- a/actionpack/lib/action_controller/routing/route.rb +++ b/actionpack/lib/action_controller/routing/route.rb @@ -35,6 +35,11 @@ module ActionController segment.key if segment.respond_to? :key end.compact end + + def required_segment_keys + required_segments = segments.select {|seg| (!seg.optional? && !seg.is_a?(DividerSegment)) || seg.is_a?(PathSegment) } + required_segments.collect { |seg| seg.key if seg.respond_to?(:key)}.compact + end # Build a query string from the keys of the given hash. If +only_keys+ # is given (as an array), only the keys indicated will be used to build diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb index 3bb25dbba9..89cdf9d0f5 100644 --- a/actionpack/lib/action_controller/routing/route_set.rb +++ b/actionpack/lib/action_controller/routing/route_set.rb @@ -185,6 +185,14 @@ module ActionController end url_for(#{hash_access_method}(opts)) + + end + #Add an alias to support the now deprecated formatted_* URL. + def formatted_#{selector}(*args) + ActiveSupport::Deprecation.warn( + "formatted_#{selector}() has been deprecated. please pass format to the standard" + + "#{selector}() method instead.", caller) + #{selector}(*args) end protected :#{selector} end_eval @@ -361,7 +369,7 @@ module ActionController end # don't use the recalled keys when determining which routes to check - routes = routes_by_controller[controller][action][options.keys.sort_by { |x| x.object_id }] + routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }] routes.each do |route| results = route.__send__(method, options, merged, expire_on) diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb index f6b03edcca..5dda3d4d00 100644 --- a/actionpack/lib/action_controller/routing/segments.rb +++ b/actionpack/lib/action_controller/routing/segments.rb @@ -308,5 +308,36 @@ module ActionController end end end + + # The OptionalFormatSegment allows for any resource route to have an optional + # :format, which decreases the amount of routes created by 50%. + class OptionalFormatSegment < DynamicSegment + + def initialize(key = nil, options = {}) + super(:format, {:optional => true}.merge(options)) + end + + def interpolation_chunk + "." + super + end + + def regexp_chunk + '(\.[^/?\.]+)?' + end + + def to_s + '(.:format)?' + end + + #the value should not include the period (.) + def match_extraction(next_capture) + %[ + if (m = match[#{next_capture}]) + params[:#{key}] = URI.unescape(m.from(1)) + end + ] + end + end + end end -- cgit v1.2.3