Rails: ¿Cómo obtener el nombre de la clase del modelo en función del nombre de la clase del controlador?

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

Respuestas:

190

Esto lo hará:

class HouseBuyersController < ApplicationController

  def index
    @model_name = controller_name.classify
  end

end

Esto suele ser necesario cuando se abstraen las acciones del controlador:

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
fuente
@model_name = controller_name.classify # devuelve "HouseBuyers" ¡Gracias!
Peter Ehrlich
1
ActiveSupport :: Inflector es increíble
Jared Beck
Dependiendo de sus necesidades (esta pregunta no especifica ningún detalle), puede hacerlo controller_name.sub('_', ' ').titleizepara obtener "compradores de casas".
usuario664833
Podría ser bueno mover la lógica (para obtener la clase de modelo) a un método de utilidad separado. Aún mejor si el resultado se almacena de forma constante, para acelerar el acceso. Puede usar new.controller_name.classify.constantizeen la definición de clase.
Kelvin
Creo que vale la pena señalar que esto incluso funcionará en el controlador de la aplicación, dependiendo de qué controlador herede.
weltschmerz
40

Si su controlador y modelo están en el mismo espacio de nombres, entonces lo que quiere es

controller_path.classify

controller_pathte da el espacio de nombres; controller_nameno lo hace.

Por ejemplo, si su controlador es

Admin::RolesController

luego:

controller_path.classify # "Admin::Role" # CORRECT
controller_name.classify # "Role"        # INCORRECT
Mate
fuente
6

Es un truco, pero si su modelo lleva el nombre del controlador, entonces:

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

... le daría "HouseBuyer" en su variable de instancia @model_name.

Nuevamente, esto supone una gran suposición de que "HouseBuyersController" solo se ocupa de los modelos "HouseBuyer".

Scott
fuente
4

Para espacios de nombres que funcionan:

def resource_class
 controller_path.classify.constantize
end
hachpai
fuente
0

Esto no es posible si está utilizando el MVC predeterminado, que su código no parece seguir. Su controlador parece ser un modelo, pero tal vez solo tenga un tipo allí. De todos modos, los controladores y los modelos están fundamentalmente separados en Rails MVC, por lo que los controladores no pueden saber con qué modelo están asociados.

Por ejemplo, podría tener un modelo llamado publicación. Esto puede tener un controlador posts_controller o podría tener un controlador como articles_controller. Rails solo conoce los modelos cuando define el código real en el controlador, como

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

En los controladores estándar de rieles no hay forma de saber cuál es el modelo.

thenengah
fuente
0

La solución aceptada no funcionó para mí ya que mi controlador y modelo tenían un espacio de nombres. En cambio, se me ocurrió el siguiente método:

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