33

I'm trying to build a RESTful app to actually manage many kind of configurable objects, so there are a large amount of "resource" types, and hence a lot of controllers. I'm still at the POC phase, so it will be nice if I can show all controllers in a first navigation page, so any easy way (programmable) to do that?

John Topley
  • 113,588
  • 46
  • 195
  • 237
Kevin Yu
  • 1,423
  • 4
  • 15
  • 19

7 Answers7

45

In Rails 3.1+:

Rails.application.routes

This will give you all the controllers, actions and their routes if you have their paths in your routes.rb file.

For example:

routes= Rails.application.routes.routes.map do |route|
  {alias: route.name, path: route.path, controller: route.defaults[:controller], action: route.defaults[:action]}
end

Update: For Rails 3.2, Journal engine path changed, so the code becomes:

routes= Rails.application.routes.routes.map do |route|
  {alias: route.name, path: route.path.spec.to_s, controller: route.defaults[:controller], action: route.defaults[:action]}
end

Update: Still working for Rails 4.2.7. To extract the list of controllers (per actual question), you can simply extract the controller and uniq

controllers = Rails.application.routes.routes.map do |route|
  route.defaults[:controller]
end.uniq
John Hinnegan
  • 5,864
  • 2
  • 48
  • 64
nurettin
  • 11,090
  • 5
  • 65
  • 85
30
ApplicationController.subclasses

It'll get you started, but keep in mind that in development mode you won't see much, because it will only show you what's actually been loaded. Fire it up in production mode, and you should see a list of all of your controllers.

jdl
  • 17,702
  • 4
  • 51
  • 54
  • 5
    You can require all files in "#{RAILS_ROOT}/app/controllers" to populate your list in development mode. – EmFi Oct 14 '09 at 05:49
  • It is important to note that this works in production mode but not in development mode, since the controllers are loaded lazily. Fire up your app in rails console mode and look at the subclasses/descendants and you won't see any. Type in the name of one of the controllers, and then the named class will appear as a subclass. ActiveAdmin seems to do a good job at this... you might want to check out their code on GitHub. – Raels Jan 23 '14 at 13:05
  • 1
    This is not a complete solution because It does not get all controllers, only direct subclasses of AplicationController. If you have two levels of nesting in your hierarchy you will not gat all of them. Use ApplicationController.descendants instead. And for getting all controllers at load time you can use Rails.application.eager_load! in your development or test environment initializers but be aware thar it will load all rails application an it can slow down boot and have any side effects. – Ricardo Vila Feb 02 '17 at 08:56
  • Thanks for explaining this I was wondering why ApplicationController.subclasses wasn't showing much! – fatfrog Jan 18 '22 at 16:54
10

While @jdl's method will work in a number of situations it fails if you have controller subclasses (e.g. ContactPageController inherits from PageController which inherits from ApplicationController) .

Therefore a better method is to use:

::ApplicationController.descendants

Using routes may not work if you have a complex app where parts are abstracted as engines, these will be hidden.

Jakub Hampl
  • 39,863
  • 10
  • 77
  • 106
8

I particularly liked @jdl solution

ApplicationController.subclasses

But in my case, where I really needed all the controller names in underscore format (I don't have subdirs eg: /admin) I used the following:

Dir[Rails.root.join('app/controllers/*_controller.rb')].map { |path| path.match(/(\w+)_controller.rb/); $1 }.compact
ecoologic
  • 10,202
  • 3
  • 62
  • 66
4

Google: 'rails list controllers'

First result.

http://snippets.dzone.com/posts/show/4792


After learning about the subclasses, I think the code from my link could be done simply as..

ApplicationController.subclasses.each do |c|
  puts "Controller: #{c}"
  puts "Actions: #{c.constantize.action_methods.collect{|a| a.to_s}.join(', ')}"
end
Jim
  • 5,557
  • 1
  • 20
  • 18
  • 1
    If you're going to list controllers and actions, why not just use rake routes? Sure the output is messy, but that's fixed by expanding your terminal window. – EmFi Oct 14 '09 at 07:33
  • I just was putting down quick code that would be similar to what the link was doing. Practicing a bit so I remember. – Jim Oct 14 '09 at 08:00
3

Another solution (if you're in Rails 5) and in Development and need to map controllers and actions:

Rails.application.routes.set.anchored_routes.map(&:defaults)

You can reject [:internal] if needed:

.reject { |route| route[:internal] }
arzezak
  • 31
  • 1
2
Dir[Rails.root.join('app/controllers/*_controller.rb')].map { |path| (path.match(/(\w+)_controller.rb/); $1).camelize+"Controller" }

This gives us the exact name of the controller as it appears within the controller file.

Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102