mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Simply track controller namespaces instead of a complete list of
possible controllers to route to
This commit is contained in:
parent
7fe19d415a
commit
2fbd6f46fd
2 changed files with 22 additions and 47 deletions
|
@ -265,6 +265,7 @@ module ActionDispatch
|
||||||
|
|
||||||
SEPARATORS = %w( / . ? )
|
SEPARATORS = %w( / . ? )
|
||||||
HTTP_METHODS = [:get, :head, :post, :put, :delete, :options]
|
HTTP_METHODS = [:get, :head, :post, :put, :delete, :options]
|
||||||
|
CONTROLLER_REGEXP = /[_a-zA-Z0-9]+/
|
||||||
|
|
||||||
# The root paths which may contain controller files
|
# The root paths which may contain controller files
|
||||||
mattr_accessor :controller_paths
|
mattr_accessor :controller_paths
|
||||||
|
@ -277,7 +278,11 @@ module ActionDispatch
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def controller_constraints
|
def controller_constraints
|
||||||
@controller_constraints ||= Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) })
|
@controller_constraints ||= begin
|
||||||
|
source = controller_namespaces.map { |ns| "#{Regexp.escape(ns)}/#{CONTROLLER_REGEXP.source}" }
|
||||||
|
source << CONTROLLER_REGEXP.source
|
||||||
|
Regexp.compile(source.sort.reverse.join('|'))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear_controller_cache!
|
def clear_controller_cache!
|
||||||
|
@ -285,57 +290,25 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# Returns the array of controller names currently available to ActionController::Routing.
|
def controller_namespaces
|
||||||
def possible_controllers
|
namespaces = Set.new
|
||||||
possible_controllers = []
|
|
||||||
|
|
||||||
# Find any controller classes already in memory
|
# Find any nested controllers already in memory
|
||||||
ActionController::Base.subclasses.each do |klass|
|
ActionController::Base.subclasses.each do |klass|
|
||||||
controller_name = klass.underscore
|
controller_name = klass.underscore
|
||||||
controller_name.gsub!(/_controller\Z/, '')
|
namespaces << controller_name.split('/')[0...-1].join('/')
|
||||||
possible_controllers << controller_name
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Find controllers in controllers/ directory
|
# Find namespaces in controllers/ directory
|
||||||
paths = controller_paths.select { |path| File.directory?(path) && path != "." }
|
controller_paths.each do |load_path|
|
||||||
seen_paths = Hash.new {|h, k| h[k] = true; false}
|
load_path = File.expand_path(load_path)
|
||||||
normalize_paths(paths).each do |load_path|
|
|
||||||
Dir["#{load_path}/**/*_controller.rb"].collect do |path|
|
Dir["#{load_path}/**/*_controller.rb"].collect do |path|
|
||||||
next if seen_paths[path.gsub(%r{^\.[/\\]}, "")]
|
namespaces << File.dirname(path).sub(/#{load_path}\/?/, '')
|
||||||
|
|
||||||
controller_name = path[(load_path.length + 1)..-1]
|
|
||||||
|
|
||||||
controller_name.gsub!(/_controller\.rb\Z/, '')
|
|
||||||
possible_controllers << controller_name
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# remove duplicates
|
namespaces.delete('')
|
||||||
possible_controllers.uniq!
|
namespaces
|
||||||
|
|
||||||
possible_controllers
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an array of paths, cleaned of double-slashes and relative path references.
|
|
||||||
# * "\\\" and "//" become "\\" or "/".
|
|
||||||
# * "/foo/bar/../config" becomes "/foo/config".
|
|
||||||
# The returned array is sorted by length, descending.
|
|
||||||
def normalize_paths(paths)
|
|
||||||
# do the hokey-pokey of path normalization...
|
|
||||||
paths = paths.collect do |path|
|
|
||||||
path = path.
|
|
||||||
gsub("//", "/"). # replace double / chars with a single
|
|
||||||
gsub("\\\\", "\\"). # replace double \ chars with a single
|
|
||||||
gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it
|
|
||||||
|
|
||||||
# eliminate .. paths where possible
|
|
||||||
re = %r{[^/\\]+[/\\]\.\.[/\\]}
|
|
||||||
path.gsub!(re, "") while path.match(re)
|
|
||||||
path
|
|
||||||
end
|
|
||||||
|
|
||||||
# start with longest path, first
|
|
||||||
paths = paths.uniq.sort_by { |path| - path.length }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,11 +27,13 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless controller = controller(params)
|
||||||
|
return [417, {}, []]
|
||||||
|
end
|
||||||
|
|
||||||
if env['action_controller.recognize']
|
if env['action_controller.recognize']
|
||||||
controller(params)
|
|
||||||
[200, {}, params]
|
[200, {}, params]
|
||||||
else
|
else
|
||||||
controller = controller(params)
|
|
||||||
controller.action(params[:action]).call(env)
|
controller.action(params[:action]).call(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,8 +44,8 @@ module ActionDispatch
|
||||||
controller = "#{params[:controller].camelize}Controller"
|
controller = "#{params[:controller].camelize}Controller"
|
||||||
ActiveSupport::Inflector.constantize(controller)
|
ActiveSupport::Inflector.constantize(controller)
|
||||||
end
|
end
|
||||||
rescue NameError => e
|
rescue NameError
|
||||||
raise ActionController::RoutingError, e.message
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge_default_action!(params)
|
def merge_default_action!(params)
|
||||||
|
|
Loading…
Reference in a new issue