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

Tab*_*rez 34 reflection methods controller ruby-on-rails ruby-on-rails-3

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

  1. 应用程序中所有控制器的列表.
  2. 给定控制器中所有操作的列表.

例如,我是一个具有"添加"和"编辑"操作的产品控制器.我是否可以通过编程方式提取这些操作的名称以向用户显示支持哪些操作?

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

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

Tabrez

Yeh*_*atz 105

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

ApplicationController.descendants
Run Code Online (Sandbox Code Playgroud)

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

Rails.application.eager_load!
Run Code Online (Sandbox Code Playgroud)

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

PostsController.action_methods
Run Code Online (Sandbox Code Playgroud)

这将返回一个Set包含控制器中所有方法的列表,这些方法是"操作"(使用Rails用来决定方法是否是路由到的有效操作的相同逻辑).

  • 值得一提的是,通过调用`.action_methods`,您只能获得类中定义的公共方法(= actions)列表.由于Rails可以在控制器中没有实际方法的情况下渲染模板,因此可能会导致应用程序中的安全漏洞. (2认同)

fan*_*ing 5

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


Eva*_*own 5

我有一个类似的问题;就我而言,它用于编写控制器测试。我想对某些控制器的每个操作运行某些基本测试(例如,如果用户未登录,则返回 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
Run Code Online (Sandbox Code Playgroud)

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

actions_for_controller('posts')
Run Code Online (Sandbox Code Playgroud)

你会得到:

['show', 'create', 'edit', 'destroy'] (or whatever)
Run Code Online (Sandbox Code Playgroud)

如果你想要一个所有控制器的列表,应该这样做:

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
Run Code Online (Sandbox Code Playgroud)


Abr*_*ram 5

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

ApplicationController.descendants.each do |controller|
  puts controller.name
  controller.action_methods.each do |action|
    puts '  ' + action
  end
end
Run Code Online (Sandbox Code Playgroud)

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