wake-up-neo.com

Wie bekomme ich eine Liste der Controller und Aktionen in Ruby auf Schienen?

In Rails kann ich den Namen des aktuellen Controllers über controller_name und die aktuelle Aktion durch Aufrufen von action_name abrufen. Ich suche nach einer ähnlichen Laufzeitreflexion, um Folgendes abzurufen:

  1. Liste aller Controller in der Anwendung.
  2. Liste aller Aktionen in einem bestimmten Controller.

Zum Beispiel ein Produkt-Controller, der Aktionen zum Hinzufügen und Bearbeiten hat. Kann ich die Namen dieser Aktionen programmgesteuert abrufen, um dem Benutzer zu zeigen, welche Vorgänge unterstützt werden?

Ich habe mir eine Methode angesehen, die die Verwendung von ActionController::Routing::Routes.named_routes.routes.each aufruft, aber ich konnte das nicht zum Laufen bringen. Ich habe einen nicht initialisierten konstanten ActionDispatch::Routing::Routes-Fehler erhalten, als ich ihn verwendet habe.

Wenn es ein gutes Tutorial oder Dokument gibt, das mir helfen kann, die Rails-Reflexionsfähigkeiten zu verstehen. Ich habe danach gesucht, aber meistens habe ich Blogs mit Bezug zu aktiver Schallplattenreflexion. Ich suche etwas, mit dem ich Informationen zu Controllern und Aktionen/Methoden zur Laufzeit abrufen kann.
Vielen Dank,

Tabrez

32
Tabrez

Der einfachste Weg, eine Liste von Controller-Klassen zu erhalten, ist:

ApplicationController.descendants

Da die Klassen jedoch faul geladen werden, müssen Sie eifrig alle Ihre Klassen laden, bevor Sie dies tun. Denken Sie daran, dass diese Methode Zeit in Anspruch nimmt und Ihren Startvorgang verlangsamt:

Rails.application.eager_load!

Um alle Aktionen in einem Controller abzurufen, verwenden Sie action_methods

PostsController.action_methods

Dies gibt eine Set zurück, die eine Liste aller Methoden in Ihrem Controller enthält, die "Aktionen" sind (unter Verwendung derselben Logik, mit der Rails entscheidet, ob eine Methode eine gültige Aktion ist, an die weitergeleitet werden soll).

102
Yehuda Katz

PostsController.action_methods gibt alle Aktionen von PostsController zurück, einschließlich des vererbten. Ich habe PostsController.instance_methods(false) nicht gefunden, was ich will. Ich werde alle Instanzmethoden von PostsController zurückgeben und nicht vererbt, genau das, was ich will. 

5
fangxing

Ich hatte ein ähnliches Problem. In meinem Fall war es das Schreiben von Controller-Tests. Es gibt bestimmte grundlegende Tests, die ich für jede Aktion für bestimmte Controller ausführen möchte (z. B. 401 zurückgeben, wenn der Benutzer nicht angemeldet ist). Das Problem mit der Lösung von action_methods besteht darin, dass alle Methoden der Controller-Klasse abgerufen werden, auch wenn die Methode keine entsprechende Route in config/routes.rb hat.

Folgendes habe ich am Ende getan:

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

Wenn Sie also eine Liste von Aktionen für PostsController wünschen, würden Sie sagen:

actions_for_controller('posts')

Und Sie würden bekommen:

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

Wenn Sie eine Liste aller Controller haben möchten, sollten Sie Folgendes tun:

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

Wir bereinigen nicht verwendete Controller und Aktionen. Deshalb wollte ich eine vollständige Liste erstellen, um sie zum Löschen zu markieren. Folgendes habe ich letztendlich getan

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

Das liefert eine schöne Liste mit Aktionen, die unter Controllernamen eingerückt sind.

0
Abram