aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/routing.rb
diff options
context:
space:
mode:
authorMichael Koziarski <michael@koziarski.com>2007-09-09 00:18:55 +0000
committerMichael Koziarski <michael@koziarski.com>2007-09-09 00:18:55 +0000
commit80ff0b9f1c07eae7668680fd12335ffa218e53ac (patch)
tree42307295c7d16ee3a778ec74b6f3becb0b5fb2ab /actionpack/lib/action_controller/routing.rb
parent7ace0a654c46cf9ca57f42981c826eace21fa42c (diff)
downloadrails-80ff0b9f1c07eae7668680fd12335ffa218e53ac.tar.gz
rails-80ff0b9f1c07eae7668680fd12335ffa218e53ac.tar.bz2
rails-80ff0b9f1c07eae7668680fd12335ffa218e53ac.zip
Optimise named route generation when using positional arguments. Closes #9450 [Koz]
This change delivers significant performance benefits for the most common usage scenarios for modern rails applications by avoiding the costly trip through url_for. Initial benchmarks indicate this is between 6 and 20 times as fast. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7421 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack/lib/action_controller/routing.rb')
-rw-r--r--actionpack/lib/action_controller/routing.rb40
1 files changed, 32 insertions, 8 deletions
diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb
index 4cf9b010ba..d20c17c30e 100644
--- a/actionpack/lib/action_controller/routing.rb
+++ b/actionpack/lib/action_controller/routing.rb
@@ -1,6 +1,7 @@
require 'cgi'
require 'uri'
require 'action_controller/polymorphic_routes'
+require 'action_controller/routing_optimisation'
class Object
def to_param
@@ -255,6 +256,11 @@ module ActionController
mattr_accessor :controller_paths
self.controller_paths = []
+ # Indicates whether or not optimise the generated named
+ # route helper methods
+ mattr_accessor :optimise_named_routes
+ self.optimise_named_routes = true
+
# A helper module to hold URL related helpers.
module Helpers
include PolymorphicRoutes
@@ -325,13 +331,25 @@ module ActionController
end
class Route #:nodoc:
- attr_accessor :segments, :requirements, :conditions
+ attr_accessor :segments, :requirements, :conditions, :optimise
def initialize
@segments = []
@requirements = {}
@conditions = {}
end
+
+ # Indicates whether the routes should be optimised with the string interpolation
+ # version of the named routes methods.
+ def optimise?
+ @optimise
+ end
+
+ def segment_keys
+ segments.collect do |segment|
+ segment.key if segment.respond_to? :key
+ end.compact
+ end
# Write and compile a +generate+ method for this Route.
def write_generation
@@ -381,6 +399,7 @@ module ActionController
end
requirement_conditions * ' && ' unless requirement_conditions.empty?
end
+
def generation_structure
segments.last.string_structure segments[0..-2]
end
@@ -977,9 +996,15 @@ module ActionController
requirements = assign_route_options(segments, defaults, requirements)
route = Route.new
+
route.segments = segments
route.requirements = requirements
route.conditions = conditions
+
+ # Routes cannot use the current string interpolation method
+ # if there are user-supplied :requirements as the interpolation
+ # code won't raise RoutingErrors when generating
+ route.optimise = !options.key?(:requirements) && ActionController::Routing.optimise_named_routes
if !route.significant_keys.include?(:action) && !route.requirements[:action]
route.requirements[:action] = "index"
@@ -1051,7 +1076,7 @@ module ActionController
# named routes.
class NamedRouteCollection #:nodoc:
include Enumerable
-
+ include ActionController::Routing::Optimisation
attr_reader :routes, :helpers
def initialize
@@ -1128,15 +1153,15 @@ module ActionController
def define_url_helper(route, name, kind, options)
selector = url_helper_name(name, kind)
-
# The segment keys used for positional paramters
- segment_keys = route.segments.collect do |segment|
- segment.key if segment.respond_to? :key
- end.compact
+
hash_access_method = hash_access_name(name, kind)
@module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks
def #{selector}(*args)
+
+ #{generate_optimisation_block(route, kind)}
+
opts = if args.empty? || Hash === args.first
args.first || {}
else
@@ -1154,7 +1179,7 @@ module ActionController
# foo_url(bar, baz, bang, :sort_by => 'baz')
#
options = args.last.is_a?(Hash) ? args.pop : {}
- args = args.zip(#{segment_keys.inspect}).inject({}) do |h, (v, k)|
+ args = args.zip(#{route.segment_keys.inspect}).inject({}) do |h, (v, k)|
h[k] = v
h
end
@@ -1167,7 +1192,6 @@ module ActionController
@module.send(:protected, selector)
helpers << selector
end
-
end
attr_accessor :routes, :named_routes