Rails: как получить имя класса модели на основе имени класса контроллера?

Ответы:

190

Это сделает это:

class HouseBuyersController < ApplicationController

  def index
    @model_name = controller_name.classify
  end

end

Это часто требуется при абстрагировании действий контроллера:

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
Малклок
источник
@model_name = controller_name.classify # возвращает "HouseBuyers" спасибо!
Питер Эрлих
1
ActiveSupport :: Inflector - это круто
Джаред Бек
В зависимости от ваших потребностей (в этом вопросе не уточняются детали) вы можете controller_name.sub('_', ' ').titleizeполучить «Покупателей жилья».
user664833
Было бы неплохо переместить логику (для получения класса модели) в отдельный служебный метод. Еще лучше, если результат будет сохранен в константе, чтобы ускорить доступ. Вы можете использовать new.controller_name.classify.constantizeв определении класса.
Кельвин
Думаю, стоит отметить, что это будет работать даже в контроллере приложения в зависимости от того, какой контроллер унаследовал от него.
weltschmerz
40

Если ваш контроллер и модель находятся в одном пространстве имен, то вам нужно

controller_path.classify

controller_pathдает вам пространство имен; controller_nameнет.

Например, если ваш контроллер

Admin::RolesController

затем:

controller_path.classify # "Admin::Role" # CORRECT
controller_name.classify # "Role"        # INCORRECT
Мэтт
источник
6

Это немного похоже на взлом, но если ваша модель названа в честь имени вашего контроллера, тогда:

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

... даст вам "HouseBuyer" в вашей переменной экземпляра @model_name.

Опять же, здесь делается огромное предположение, что HouseBuyersController имеет дело только с моделями HouseBuyer.

Скотт
источник
4

Для работающих пространств имен:

def resource_class
 controller_path.classify.constantize
end
хачпай
источник
0

Это невозможно, если вы используете MVC по умолчанию, которому ваш код не следует. Ваш контроллер кажется моделью, но, может быть, у вас только что есть тип. В любом случае контроллеры и модели в Rails MVC принципиально разделены, поэтому контроллеры не могут знать, с какой моделью они связаны.

Например, у вас может быть модель с именем post. Это может быть контроллер posts_controller или такой контроллер, как article_controller. Rails знает о моделях только тогда, когда вы определяете фактический код в контроллере, например

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

В стандартных контроллерах rails нет возможности узнать, что это за модель.

Thenengah
источник
0

Принятое решение не сработало для меня, поскольку мой контроллер и модель были помещены в пространство имен. Вместо этого я придумал следующий метод:

def controllers_model
  (self.class.name.split('::')[0..-2] << controller_name.classify).join('::')
end
Stoffus
источник