以编程方式获取给定命名空间中所有控制器的列表

时间:2013-02-07 10:50:51

标签: ruby-on-rails ruby ruby-on-rails-3.2

我们的Rails 3.2应用程序有管理面板。管理面板分为模块。例如,有Admin::Searching。我想重构一些重复和硬编码的部分。例如:

<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>

正在搜索导航部分,添加另一个控制器后,您必须手动更改它。 我想要的是,获取Admin::Searching 中所有控制器的列表(此命名空间中的控制器是Admin::AdminController的子类)。我相信有可能从Rails api以优雅的方式做到这一点。然后它可以推广到所有模块选项卡。

我已经尝试检查Admin :: AdminController.subclasses,但是该数组中的类是延迟加载的,所以在点击Terms之后,例如,在服务器重启后,只有一个元素[Admin::Searching::TermsController],之后访问其他模块还有其他控制器。我可以迭代它们并基于controller_path结果,仅过滤admin/search个控制器。也许有可能从路线结束?我的意思是,我可以从Rails.application.routes.routes中获取给定名称空间中的所有控制器吗?

我不想进入文件系统。我知道我可以使用Dir扫描管理员/搜索目录,但效率很低。

1 个答案:

答案 0 :(得分:2)

我有一个很好的答案描述Module#constantsModule#const_get的使用,但后来我读到你问题的后半部分,并意识到这种技术可能不会出于同样的原因Admin::AdminController.subclasses没有 - 这是因为Rails根据需要懒洋洋地加载控制器类。

在您的情况下,我可能最终会进行目录扫描。你认为它效率低下,但是当进行动态加载和填充时,Rails和许多Ruby宝石最终会进入文件系统。

现在,您希望在加载之前找到所有(相关)控制器。结合生产中的洞察力,控制器的数量不会改变。

我想说的是,继续进行Dir扫描,但是在初始值设定项(config/initializers下的文件)中进行扫描,因此它只会在开始时执行一次你的应用程序。

所以,可以想象,

# config/initializers/admin.rb
module Admin
  CONTROLLERS = begin
    # Do a directory scan of app/controllers/admin looking for relevant files
  end
end