web-dev-qa-db-fra.com

Comment obtenir la liste des contrôleurs et des actions dans Ruby on rails?

Dans Rails, je peux obtenir le nom du contrôleur actuel via le nom du contrôleur et l'action en cours en appelant nom_action. Je recherche une réflexion similaire à l'exécution pour obtenir les éléments suivants:

  1. Liste de tous les contrôleurs de l'application.
  2. Liste de toutes les actions dans un contrôleur donné.

Par exemple, j’ai un contrôleur de produit ayant les actions "ajouter" et "éditer". Puis-je extraire les noms de ces actions par programme pour montrer à l'utilisateur quelles opérations sont supportées?

J'ai examiné une méthode qui appelle l'utilisation de ActionController::Routing::Routes.named_routes.routes.each mais je ne pouvais pas le faire fonctionner. J'ai eu l'erreur constante ActionDispatch::Routing::Routes non initialisée quand je l'ai utilisée.

S'il existe un bon didacticiel ou un document pouvant m'aider à comprendre les capacités de réflexion de Rails. Je l'ai cherché mais j'ai surtout eu des blogs actifs sur la réflexion. Je recherche quelque chose qui me permette d'obtenir des informations sur les contrôleurs et les actions/méthodes au moment de l'exécution.
Merci,

Tabrez

32
Tabrez

Le moyen le plus simple d’obtenir une liste des classes de contrôleur est:

ApplicationController.descendants

Cependant, comme les classes sont chargées paresseusement, vous devrez charger toutes vos classes avant de le faire. Gardez à l'esprit que cette méthode prendra du temps et ralentira votre démarrage:

Rails.application.eager_load!

Pour obtenir toutes les actions dans un contrôleur, utilisez action_methods

PostsController.action_methods

Ceci renverra une Set contenant une liste de toutes les méthodes de votre contrôleur qui sont des "actions" (en utilisant la même logique que Rails utilise pour décider si une méthode est une action valide vers laquelle se diriger).

102
Yehuda Katz

PostsController.action_methods renverra toutes les actions de PostsController, y compris celles héritées, ce n'est pas ce que je veux, j'ai trouvé PostsController.instance_methods(false), ce qui renverra toutes les méthodes d'instance de PostsController sans inclure héritées, exactement ce que je veux. 

5
fangxing

J'avais un problème similaire; dans mon cas, c'était pour écrire des tests de contrôleur. Je souhaite exécuter certains tests de base sur chaque action de certains contrôleurs (par exemple, renvoyer 401 si l'utilisateur n'est pas connecté). Le problème avec la solution action_methods est qu’il récupère toutes les méthodes de la classe du contrôleur, même si la méthode n’a pas de route correspondante dans config/routes.rb.

Voici ce que j'ai fini par faire:

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

Donc, si vous vouliez une liste d’actions pour PostsController, vous diriez:

actions_for_controller('posts')

Et vous auriez:

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

Si vous voulez une liste de tous les contrôleurs, quelque chose comme ceci devrait le faire:

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
1