How to get list of controllers and actions in ruby on rails?

前端 未结 4 728
你的背包
你的背包 2020-12-07 20:50

In rails, I can get the name of the current controller via controller_name and the current action by calling action_name. I am looking for similar runtime reflection for fet

相关标签:
4条回答
  • 2020-12-07 21:08

    The easiest way to get a list of controller classes is:

    ApplicationController.descendants
    

    However, as classes are loaded lazily, you will need to eager load all your classes before you do this. Keep in mind that this method will take time, and it will slow down your boot:

    Rails.application.eager_load!
    

    To get all the actions in a controller, use action_methods

    PostsController.action_methods
    

    This will return a Set containing a list of all of the methods in your controller that are "actions" (using the same logic Rails uses to decide whether a method is a valid action to route to).

    0 讨论(0)
  • 2020-12-07 21:13

    PostsController.action_methods will return all actions of PostsController including inherited, it's not what I want, I found PostsController.instance_methods(false), which will return all instance methods of PostsController and not include inherited, exactly what I want.

    0 讨论(0)
  • 2020-12-07 21:20

    I had a similar problem; in my case it was for writing controller tests. There are certain basic tests that I want to run on every action for certain controllers (e.g., return 401 if the user is not logged in). The problem with the action_methods solution is that it picks up all methods on the controller class, even if the method does not have a corresponding route in config/routes.rb.

    Here's what I ended up doing:

    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
    

    So if you wanted a list of actions for PostsController, you'd say:

    actions_for_controller('posts')
    

    And you would get:

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

    If you wanted a list of all controllers, something like this should do it:

    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
    
    0 讨论(0)
  • 2020-12-07 21:24

    We are cleaning out unused controllers and actions. So I wanted to create an exhaustive list to mark for deletion. Here's what I ended up doing

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

    That provides a nice list with actions indented under controller names.

    0 讨论(0)
提交回复
热议问题