Rails: Jak uzyskać nazwę klasy modelu na podstawie nazwy klasy kontrolera?

99
class HouseBuyersController < ...
  def my_method
    # How could I get here the relevant model name, i.e. "HouseBuyer" ?
  end
end
Misha Moroshko
źródło

Odpowiedzi:

190

To zrobi to:

class HouseBuyersController < ApplicationController

  def index
    @model_name = controller_name.classify
  end

end

Jest to często potrzebne podczas wyodrębniania akcji kontrolera:

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
źródło
@model_name = controller_name.classify # zwraca "HouseBuyers" dzięki!
Peter Ehrlich
1
ActiveSupport :: Inflector jest niesamowity
Jared Beck
W zależności od Twoich potrzeb (to pytanie nie określa żadnych szczegółów), możesz zrobić, controller_name.sub('_', ' ').titleizeaby uzyskać „Kupujący dom”.
user664833
Dobrze byłoby przenieść logikę (w celu uzyskania klasy modelu) do oddzielnej metody narzędziowej. Jeszcze lepiej, jeśli wynik jest przechowywany w stałej, aby przyspieszyć dostęp. Możesz użyć new.controller_name.classify.constantizew definicji klasy.
Kelvin,
Myślę, że warto zauważyć, że to zadziała nawet w kontrolerze aplikacji w zależności od tego, który kontroler po nim dziedziczy.
weltschmerz
40

Jeśli kontroler i model znajdują się w tej samej przestrzeni nazw, to chcesz

controller_path.classify

controller_pathdaje przestrzeń nazw; controller_namenie.

Na przykład, jeśli twój kontroler to

Admin::RolesController

następnie:

controller_path.classify # "Admin::Role" # CORRECT
controller_name.classify # "Role"        # INCORRECT
Matt
źródło
6

To trochę hack, ale jeśli twój model nosi nazwę po nazwie kontrolera, to:

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

... da ci „HouseBuyer” w zmiennej instancji @model_name.

Ponownie, zakłada się, że „HouseBuyersController” obsługuje tylko modele „HouseBuyer”.

Scott
źródło
4

W przypadku działających przestrzeni nazw:

def resource_class
 controller_path.classify.constantize
end
hachpai
źródło
0

Nie jest to możliwe, jeśli używasz domyślnego MVC, którego kod nie wydaje się przestrzegać. Twój kontroler wydaje się być modelem, ale może po prostu masz tam typ. W każdym razie kontrolery i modele są zasadniczo oddzielone w Rails MVC, więc kontrolery nie mogą wiedzieć, z którym modelem są skojarzone.

Na przykład możesz mieć model o nazwie post. Może to mieć kontroler post_controller lub może mieć kontroler taki jak artykuły_controller. Railsy wiedzą o modelach tylko wtedy, gdy zdefiniujesz rzeczywisty kod w kontrolerze, taki jak

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

W standardowych kontrolerach szynowych nie ma sposobu, aby dowiedzieć się, jaki jest model.

thenengah
źródło
0

Zaakceptowane rozwiązanie nie zadziałało, ponieważ mój kontroler i model miały przestrzeń nazw. Zamiast tego wymyśliłem następującą metodę:

def controllers_model
  (self.class.name.split('::')[0..-2] << controller_name.classify).join('::')
end
stoffus
źródło