aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/application/route_inspector.rb
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails/application/route_inspector.rb')
-rw-r--r--railties/lib/rails/application/route_inspector.rb104
1 files changed, 91 insertions, 13 deletions
diff --git a/railties/lib/rails/application/route_inspector.rb b/railties/lib/rails/application/route_inspector.rb
index 8c6911e6bb..5ca366c5f2 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 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|^/assets}
+ 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 initialize
+ @engines = ActiveSupport::OrderedHash.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