Rails: Wie erhalte ich den Modellklassennamen basierend auf dem Controller-Klassennamen?

99
class HouseBuyersController < ...
  def my_method
    # How could I get here the relevant model name, i.e. "HouseBuyer" ?
  end
end
Mischa Moroshko
quelle

Antworten:

190

Dies wird es tun:

class HouseBuyersController < ApplicationController

  def index
    @model_name = controller_name.classify
  end

end

Dies wird häufig benötigt, wenn Controller-Aktionen abstrahiert werden:

class HouseBuyersController < ApplicationController

  def index
    # Equivalent of @house_buyers = HouseBuyer.find(:all)
    objects = controller_name.classify.constantize.find(:all)
    instance_variable_set("@#{controller_name}", objects)
  end

end
Malclocke
quelle
@model_name = controller_name.classify # gibt "HouseBuyers" zurück, danke!
Peter Ehrlich
1
ActiveSupport :: Inflector ist fantastisch
Jared Beck
Abhängig von Ihren Bedürfnissen (diese Frage enthält keine Details) können Sie controller_name.sub('_', ' ').titleize"Hauskäufer" finden.
user664833
Es kann sinnvoll sein, die Logik (zum Abrufen der Modellklasse) in eine separate Dienstprogrammmethode zu verschieben. Noch besser, wenn das Ergebnis in einer Konstanten gespeichert wird, um den Zugriff zu beschleunigen. Sie können new.controller_name.classify.constantizein der Klassendefinition verwenden.
Kelvin
Ich denke, es ist erwähnenswert, dass dies sogar im Anwendungscontroller funktioniert, je nachdem, welcher Controller davon erbt.
Weltschmerz
40

Wenn sich Ihr Controller und Ihr Modell im selben Namespace befinden, möchten Sie Folgendes

controller_path.classify

controller_path gibt Ihnen den Namespace; controller_namenicht.

Zum Beispiel, wenn Ihr Controller ist

Admin::RolesController

dann:

controller_path.classify # "Admin::Role" # CORRECT
controller_name.classify # "Role"        # INCORRECT
Matt
quelle
6

Es ist ein bisschen wie ein Hack, aber wenn Ihr Modell nach Ihrem Controllernamen benannt ist, dann:

class HouseBuyersController < ApplicationController
  def my_method
    @model_name = self.class.name.sub("Controller", "").singularize
  end
end

... würde Ihnen "HouseBuyer" in Ihrer Instanzvariablen @model_name geben.

Dies setzt wiederum eine große Annahme voraus, dass "HouseBuyersController" nur "HouseBuyer" -Modelle behandelt.

Scott
quelle
4

Für funktionierende Namespaces:

def resource_class
 controller_path.classify.constantize
end
hachpai
quelle
0

Dies ist nicht möglich, wenn Sie die Standard-MVC verwenden, der Ihr Code nicht zu folgen scheint. Ihr Controller scheint ein Modell zu sein, aber vielleicht haben Sie dort gerade einen Typ. Auf jeden Fall sind Controller und Modelle in Rails MVC grundsätzlich getrennt, sodass Controller nicht wissen können, welchem ​​Modell sie zugeordnet sind.

Zum Beispiel könnten Sie ein Modell namens post haben. Dies kann einen Controller posts_controller oder einen Controller wie articles_controller haben. Rails kennt Modelle nur, wenn Sie den tatsächlichen Code in der Steuerung wie z

def index
  @posts = Post.all
  @posts = Article.all
end  

In Schienen-Standardsteuerungen gibt es keine Möglichkeit, das Modell zu kennen.

thenengah
quelle
0

Die akzeptierte Lösung funktionierte bei mir nicht, da mein Controller und mein Modell einen Namespace hatten. Stattdessen habe ich die folgende Methode entwickelt:

def controllers_model
  (self.class.name.split('::')[0..-2] << controller_name.classify).join('::')
end
stoffus
quelle