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?

7 Answers 7

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
Sign up to request clarification or add additional context in comments.

Comments

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.

4 Comments

You can require all files in "#{RAILS_ROOT}/app/controllers" to populate your list in development mode.
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.
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.
Thanks for explaining this I was wondering why ApplicationController.subclasses wasn't showing much!
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.

1 Comment

subclasses didn't work for active admin but your works! thank you
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

Comments

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

2 Comments

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.
I just was putting down quick code that would be similar to what the link was doing. Practicing a bit so I remember.
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] }

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.