ruby on rails - SessionsHelper en railstutorial.org: ¿Los ayudantes deben ser módulos de propósito general para el código que no se necesitan en las vistas?
ruby-on-rails encapsulation (4)
De hecho, tu sentimiento es correcto.
Lo implementaría al revés: agregue las funciones sign_in
y current_user
a ApplicationController
(o si realmente desea: en un módulo separado definido en lib
e lib
), y luego asegúrese de que el método current_user
esté disponible en la vista .
En breve:
class ApplicationController
helper_method :current_user
def sign_in
end
def current_user
@current_user ||= user_from_remember_token
end
end
Por supuesto, si tiene mucho código para colocar en su ApplicationController
, puede ensuciarse. En ese caso yo crearía un archivo lib/session_management.rb
:
module SessionManagement
def self.included(base)
base.helper_method :current_user
end
def sign_in
..
end
def current_user
..
end
end
y dentro de tu controlador puedes escribir:
class ApplicationController
include SessionManagement
end
railstutorial.org tiene una sugerencia que me parece un poco rara.
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end
La include SessionsHelper
hace que los métodos estén disponibles desde ApplicationController
, sí, pero también los hace disponibles en cualquier vista. Entiendo que la autenticación / autorización es transversal, pero ¿es este realmente el mejor lugar?
Eso me parece potencialmente un alcance demasiado amplio. El código que implementa, por ejemplo, un before_filter
que redirecciona condicionalmente (como lo hace el ejemplo railstutorial.org) en un módulo que más comúnmente contiene ayudantes de vista parece sorprendente.
¿La funcionalidad que no se necesita estrictamente en las vistas se ubicaría mejor en ApplicationController o en otro lugar?
¿O simplemente estoy pensando demasiado en esto?
Esta es una pregunta filosófica en el mismo nivel que el argumento que cuestiona el método REST proporcionado en los andamios y si vale la pena tener un andamio. Debe tener en cuenta el hecho de que el libro de tutoriales en RailsTutorial.org es una guía instructiva de cómo ponerse en marcha Rails. Así que para el propósito que sirve, creo que hace el trabajo.
Sin embargo, ¿existe un lugar mejor para colocar el código necesario entre los controladores y las vistas? Sí hay.
- Algunos pueden seguir el formulario de Railstutorial de Michael Hartl e incluir el
SessionHelper
completo en elApplicationController
- Otros pueden decidir exponer solo los ayudantes esenciales necesarios para la vista, es decir,
sign_out
,sign_out
,current_user
y similares. - Veo una sugerencia para poner dicho código en el directorio
/lib
e incluirlo donde sea necesario.
Todas son opciones viables. Lo que tome no importa mucho en el rendimiento, ya que Ruby tendría que analizar el archivo del que desea llamar (o incluir) una clase, un módulo o un método. Lo que sucede es que, antes de que se ejecute cualquier código en una clase, Ruby recorre toda la clase una vez para saber qué contiene. Todo depende de lo que uno necesite y del diseño de su aplicación.
FWIW, almaceno el usuario actual en la clase de Usuario:
class User < ActiveRecord::Base
cattr_accessor :current
...
end
Esto puede ser referenciado en los 3 niveles MVC; se establece en el controlador como tal (y también al iniciar sesión, por supuesto):
def set_current_user
User.current = (session[:user_id]) ? User.find_by_id(session[:user_id]) : nil
end
Entre otras cosas, esto me permite tener registros de auditoría en el nivel ActiveRecord que capturan al usuario actual (cuando corresponda).
Parece que se están aprovechando (furtivamente) del hecho de que, en Rails, los Helpers son solo módulos ruby.
Colocar el comportamiento que se comparte entre los Controladores en un Módulo es, en mi opinión, una buena práctica. Ponerlo en un Ayudante, por otro lado, es potencialmente engañoso y lo evitaría. Colóquelo en un módulo "estándar".