Te sugerimos que pruebes esta resolución en un entorno controlado antes de pasarlo a producción, saludos.
Solución:
Yo diría que tus instintos para mantener current_user
fuera del modelo son correctos.
Al igual que Daniel, estoy totalmente a favor de los controladores flacos y los modelos gordos, pero también hay una clara división de responsabilidades. El propósito del controlador es administrar la solicitud entrante y la sesión. El modelo debería poder responder a la pregunta “¿Puede el usuario x hacer y a este objeto?”, pero no tiene sentido que haga referencia al current_user
. ¿Qué pasa si estás en la consola? ¿Qué pasa si se está ejecutando un trabajo cron?
En muchos casos, con la API de permisos correcta en el modelo, esto se puede manejar con una sola línea before_filters
que se aplican a varias acciones. Sin embargo, si las cosas se vuelven más complejas, es posible que desee implementar una capa separada (posiblemente en lib/
) que encapsula la lógica de autorización más compleja para evitar que su controlador se sobrecargue y que su modelo se acople demasiado al ciclo de solicitud/respuesta web.
Aunque esta pregunta ha sido respondida por muchos, solo quería agregar mis dos centavos rápidamente.
El uso del enfoque #current_user en el modelo de usuario debe implementarse con precaución debido a la seguridad de subprocesos.
Está bien usar un método class/singleton en User si recuerda usar Thread.current como una forma de almacenar y recuperar sus valores. Pero no es tan fácil porque también debe restablecer Thread.current para que la próxima solicitud no herede los permisos que no debería.
El punto que estoy tratando de hacer es, si almacena el estado en variables de clase o singleton, recuerde que está tirando la seguridad de subprocesos por la ventana.
El controlador debe decirle a la instancia del modelo
Trabajar con la base de datos es el trabajo del modelo. Manejar las solicitudes web, incluido conocer al usuario de la solicitud actual, es trabajo del controlador.
Por lo tanto, si una instancia de modelo necesita conocer al usuario actual, un controlador debe informarlo.
def create
@item = Item.new
@item.current_user = current_user # or whatever your controller method is
...
end
Esto supone que Item
tiene un attr_accessor
por current_user
.
(Nota: primero publiqué esta respuesta en otra pregunta, pero acabo de notar que esa pregunta es un duplicado de esta).
Recuerda algo, que puedes optar por la opción de interpretar tu experiencia si te fue de ayuda.