如何在rails上获取ruby中的控制器和操作列表?

时间:2011-12-31 05:13:23

标签: ruby-on-rails ruby-on-rails-3 reflection methods controller

在rails中,我可以通过controller_name获取当前控制器的名称,并通过调用action_name获取当前操作。我正在寻找类似的运行时反射来获取以下内容:

  1. 应用程序中所有控制器的列表。
  2. 给定控制器中所有操作的列表。
  3. 例如,我是一个具有“添加”和“编辑”操作的产品控制器。我是否可以通过编程方式提取这些操作的名称以向用户显示支持哪些操作?

    我看过一个要求使用ActionController::Routing::Routes.named_routes.routes.each的方法 但我无法让它发挥作用。当我使用它时,我得到了未初始化的常量ActionDispatch::Routing::Routes错误。

    如果有任何好的教程或文档可以帮助我理解rails反射功能。我搜索了它,但我主要是积极的记录反射相关的博客。我正在寻找能让我在运行时获取有关控制器和动作/方法的信息的东西 谢谢,

    Tabrez

4 个答案:

答案 0 :(得分:102)

获取控制器类列表的最简单方法是:

ApplicationController.descendants

但是,由于类是懒惰加载的,因此在执行此操作之前,您需要先加载所有类。请记住,此方法需要一些时间,并且会降低启动速度:

Rails.application.eager_load!

要获取控制器中的所有操作,请使用action_methods

PostsController.action_methods

这将返回一个Set,其中包含控制器中所有方法的列表,这些方法是“操作”(使用Rails用于确定方法是否是路由到的有效操作的相同逻辑)。 / p>

答案 1 :(得分:5)

PostsController.action_methods将返回PostsController包括继承的所有操作,这不是我想要的,我找到PostsController.instance_methods(false),它将返回PostsController的所有实例方法,而不包括继承,正是我想要的。

答案 2 :(得分:1)

我有类似的问题;就我而言,这是用于编写控制器测试的。我想对某些控制器的每个操作执行某些基本测试(例如,如果用户未登录,则返回401)。 action_methods解决方案的问题在于,即使该方法在config / routes.rb中没有对应的路由,它也会拾取控制器类上的所有方法。

这就是我最终要做的:

def actions_for_controller(controller_path)
  route_defaults = Rails.application.routes.routes.map(&:defaults)
  route_defaults = route_defaults.select { |x| x[:controller] == controller_path }
  route_defaults.map { |x| x[:action] }.uniq
end

因此,如果您想要PostsController的操作列表,您会说:

actions_for_controller('posts')

您将得到:

['show', 'create', 'edit', 'destroy'] (or whatever)

如果要获取所有控制器的列表,应执行以下操作:

def controllers_list
  route_defaults = Rails.application.routes.routes.map(&:defaults)
  files = route_defaults.map { |x| "#{x[:controller]}_controller" }.uniq
  files -= ['_controller']
  files.map { |x| x.split('/').map(&:camelize).join('::').constantize }
end

答案 3 :(得分:0)

我们正在清理未使用的控制器和动作。因此,我想创建一个详尽的列表以标记为删除。这就是我最终要做的

ApplicationController.descendants.each do |controller|
  puts controller.name
  controller.action_methods.each do |action|
    puts '  ' + action
  end
end

这提供了一个不错的列表,其中包含在控制器名称下缩进的动作。