0

Our Rails 3.2 application has admin panel. Admin panel is divided into modules. For instance there is Admin::Searching. I want to refactor some repetitive and hardcoded partials. For instance:

<ul class='searching_nav'>
<% %w(tests fuzzy stats terms hits).each do |tab| %>
  <li class="<%= css_nav(tab) %>"><%= link_to tab.humanize, [:admin, :searching, tab] %></li>
<% end %>
</ul>

It is searching nav section, after adding another controller you have to change it manually. What I want is, getting list of all controllers in Admin::Searching (controllers in this namespace are subclasses of Admin::AdminController). I believe it is possible to do it in elegant way from Rails api. Then it can be generalized for all modules tabs.

I have tried checking Admin::AdminController.subclasses, but classes in that array are lazy loaded so after hitting Terms for example, after server restart, there is only one element [Admin::Searching::TermsController], and after visiting other modules there are also other controllers. I could iterate over them and base on controller_path results, filter only admin/search controllers. Maybe it is possible from the routes end? I mean, could I get all controllers in given namespace, from Rails.application.routes.routes?

I do not want to get to filesystem. I know that I could scan admin/searching directory with Dir but it is inefficient.

Casual Coder
  • 1,492
  • 2
  • 14
  • 15

1 Answers1

2

I had a whole nice answer describing the use of Module#constants and Module#const_get but then I read through to the latter part of your question and realized that this technique probably won't work for the same reason that Admin::AdminController.subclasses doesn`t—and that is because Rails lazily loads the controller classes as needed.

In your case, I would probably just end up doing a directory scan. You think it's inefficient, but Rails and lots of Ruby gems end up going to the file system anyway when doing dynamic loading and stuff.

Now, you want to find all (relevant) controllers before they're loaded anyway. Couple this with the insight that in production, the number of controllers doesn't change.

What I'm trying to say is, go ahead and do a Dir scan, but do it in an initializer (a file under config/initializers) so it only gets executed once, at the start of your app.

So, conceivably,

# config/initializers/admin.rb
module Admin
  CONTROLLERS = begin
    # Do a directory scan of app/controllers/admin looking for relevant files
  end
end
Alistair A. Israel
  • 6,417
  • 1
  • 31
  • 40
  • Ok, thanks for an answer. Still it will be executed everytime when the environment is loaded, so in rake/thor tasks and tests. I will consider it if there will be no better solution, but what about routes? There is information about namspaces and controllers in it. Can I get that info programmatically? – Casual Coder Feb 07 '13 at 16:47
  • Well, I found [How to programmatically list all controllers in Rails](http://stackoverflow.com/questions/1564278/how-to-programmatically-list-all-controllers-in-rails) which might help you. – Alistair A. Israel Feb 08 '13 at 01:59