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:
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
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).
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.
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
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.