Rails: Comment obtenir le nom de la classe du modèle en fonction du nom de la classe du contrôleur?

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

Réponses:

190

Cela le fera:

class HouseBuyersController < ApplicationController

  def index
    @model_name = controller_name.classify
  end

end

Ceci est souvent nécessaire lors de l'analyse des actions du contrôleur:

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
la source
@model_name = controller_name.classify # renvoie "HouseBuyers" merci!
Peter Ehrlich
1
ActiveSupport :: Inflector is awesome
Jared Beck
En fonction de vos besoins, (cette question ne précise aucun détail), vous pouvez faire controller_name.sub('_', ' ').titleizepour obtenir des «acheteurs de maison».
user664833
Il peut être bon de déplacer la logique (pour obtenir la classe de modèle) dans une méthode utilitaire distincte. Encore mieux si le résultat est stocké dans une constante, pour accélérer l'accès. Vous pouvez utiliser new.controller_name.classify.constantizedans la définition de classe.
Kelvin
Je pense qu'il vaut la peine de noter que cela fonctionnera même dans le contrôleur d'application en fonction du contrôleur en hérite.
weltschmerz
40

Si votre contrôleur et votre modèle sont dans le même espace de noms, alors ce que vous voulez est

controller_path.classify

controller_pathvous donne l'espace de noms; controller_namepas.

Par exemple, si votre contrôleur est

Admin::RolesController

puis:

controller_path.classify # "Admin::Role" # CORRECT
controller_name.classify # "Role"        # INCORRECT
Mat
la source
6

C'est un peu un hack, mais si votre modèle est nommé d'après le nom de votre contrôleur, alors:

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

... vous donnerait "HouseBuyer" dans votre variable d'instance @model_name.

Encore une fois, cela suppose que "HouseBuyersController" ne traite que des modèles "HouseBuyer".

Scott
la source
4

Pour les espaces de noms fonctionnant:

def resource_class
 controller_path.classify.constantize
end
hachpai
la source
0

Cela n'est pas possible si vous utilisez le MVC par défaut, que votre code ne semble pas suivre. Votre contrôleur semble être un modèle, mais peut-être que vous venez d'en avoir un type. Quoi qu'il en soit, les contrôleurs et les modèles sont fondamentalement séparés dans Rails MVC afin que les contrôleurs ne puissent pas savoir à quel modèle ils sont associés.

Par exemple, vous pourriez avoir un modèle nommé post. Cela peut avoir un contrôleur posts_controller ou pourrait avoir un contrôleur comme articles_controller. Rails ne connaît les modèles que lorsque vous définissez le code réel dans le contrôleur tel que

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

Dans les contrôleurs standard de rails, il n'y a aucun moyen de savoir quel est le modèle.

alorsengah
la source
0

La solution acceptée ne fonctionnait pas pour moi car mon contrôleur et mon modèle étaient à espace de noms. Au lieu de cela, j'ai proposé la méthode suivante:

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