diff options
Diffstat (limited to 'railties/lib/rails/application/route_inspector.rb')
-rw-r--r-- | railties/lib/rails/application/route_inspector.rb | 106 |
1 files changed, 92 insertions, 14 deletions
diff --git a/railties/lib/rails/application/route_inspector.rb b/railties/lib/rails/application/route_inspector.rb index 8c6911e6bb..b23fb3e920 100644 --- a/railties/lib/rails/application/route_inspector.rb +++ b/railties/lib/rails/application/route_inspector.rb @@ -1,35 +1,113 @@ +require 'delegate' + module Rails class Application + class RouteWrapper < SimpleDelegator + def endpoint + rack_app ? rack_app.inspect : "#{controller}##{action}" + end + + def constraints + requirements.except(:controller, :action) + end + + def rack_app(app = self.app) + @rack_app ||= begin + class_name = app.class.name.to_s + if class_name == "ActionDispatch::Routing::Mapper::Constraints" + rack_app(app.app) + elsif ActionDispatch::Routing::Redirect === app || class_name !~ /^ActionDispatch::Routing/ + app + end + end + end + + def verb + super.source.gsub(/[$^]/, '') + end + + def path + super.spec.to_s + end + + def name + super.to_s + end + + def reqs + @reqs ||= begin + reqs = endpoint + reqs += " #{constraints.inspect}" unless constraints.empty? + reqs + end + end + + def controller + requirements[:controller] || ':controller' + end + + def action + requirements[:action] || ':action' + end + + def internal? + path =~ %r{/rails/info/properties|^#{Rails.application.config.assets.prefix}} + end + + def engine? + rack_app && rack_app.respond_to?(:routes) + end + end + ## # This class is just used for displaying route information when someone # executes `rake routes`. People should not use this class. class RouteInspector # :nodoc: - def format all_routes, filter = nil + def initialize + @engines = Hash.new + end + + def format(all_routes, filter = nil) if filter all_routes = all_routes.select{ |route| route.defaults[:controller] == filter } end - routes = all_routes.collect do |route| + routes = collect_routes(all_routes) - reqs = route.requirements.dup - rack_app = route.app unless route.app.class.name.to_s =~ /^ActionDispatch::Routing/ + formatted_routes(routes) + + formatted_routes_for_engines + end - endpoint = rack_app ? rack_app.inspect : "#{reqs[:controller]}##{reqs[:action]}" - constraints = reqs.except(:controller, :action) + def collect_routes(routes) + routes = routes.collect do |route| + RouteWrapper.new(route) + end.reject do |route| + route.internal? + end.collect do |route| + collect_engine_routes(route) - reqs = endpoint == '#' ? '' : endpoint + {:name => route.name, :verb => route.verb, :path => route.path, :reqs => route.reqs } + end + end - unless constraints.empty? - reqs = reqs.empty? ? constraints.inspect : "#{reqs} #{constraints.inspect}" - end + def collect_engine_routes(route) + name = route.endpoint + return unless route.engine? + return if @engines[name] - verb = route.verb.source.gsub(/[$^]/, '') - {:name => route.name.to_s, :verb => verb, :path => route.path.spec.to_s, :reqs => reqs} + routes = route.rack_app.routes + if routes.is_a?(ActionDispatch::Routing::RouteSet) + @engines[name] = collect_routes(routes.routes) end + end - # Skip the route if it's internal info route - routes.reject! { |r| r[:path] =~ %r{/rails/info/properties|^/assets} } + def formatted_routes_for_engines + @engines.map do |name, routes| + ["\nRoutes for #{name}:"] + formatted_routes(routes) + end.flatten + end + def formatted_routes(routes) name_width = routes.map{ |r| r[:name].length }.max verb_width = routes.map{ |r| r[:verb].length }.max path_width = routes.map{ |r| r[:path].length }.max |