2011-03-31 6 views
18

railstutorial.org tiene una sugerencia que me parece un poco extraña.SessionsHelper in railstutorial.org: ¿Deberían los helpers ser módulos de propósito general para códigos que no se necesitan en las vistas?

It suggests this code:

class ApplicationController < ActionController::Base 
    protect_from_forgery 
    include SessionsHelper 
end 

El include SessionsHelper hace que los métodos disponibles de ApplicationController, sí, pero los pone a disposición de cualquier punto de vista, también. Entiendo que la autenticación/autorización es transversal, pero ¿este es realmente el mejor lugar?

Me parece que tiene un alcance potencialmente demasiado amplio. Parece sorprendente poner código que implemente, digamos, un before_filter que redirige condicionalmente (como lo hace el ejemplo de railstutorial.org) en un módulo que contiene más ayudantes de visualización.

¿Funcionaría mejor en ApplicationController o en otro lugar la funcionalidad no estrictamente necesaria en las vistas?

¿O simplemente estoy pensando demasiado en esto?

Respuesta

19

De hecho, su sensación es correcta.

Me gustaría poner en práctica esta al revés: agregue las funciones sign_in y current_user a ApplicationController (o si realmente quiere: en un módulo independiente se define en lib e incluirlo), y luego asegurarse de que el método current_user es disponible en la vista.

En resumen:

class ApplicationController 

    helper_method :current_user 

    def sign_in 

    end 

    def current_user 
    @current_user ||= user_from_remember_token 
    end 
end 

Por supuesto, si usted tiene una gran cantidad de código para colocar en su ApplicationController que puede causar problemas. En ese caso, me gustaría crear 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 su controlador continuación, puede simplemente escribir:

class ApplicationController 
    include SessionManagement 
end 
+0

El 'base.helper: current_user code' es incorrecto, debe ser' base.send: helper_method,: current_user' – kain

+0

Gracias @kain, pequeño error. Debería ser 'helper_method'. Pero puedes escribir 'base.helper_method,: current_user'. – nathanvda

+0

Pregunta básica: en este caso, ¿cuál es la diferencia entre usar un SessionHelper y usar un módulo SessionManagment? ¿No es un ayudante solo otro módulo? –

6

parecen estar tomando (furtivo) ventaja de que, en Rails, Helpers son solo módulos de ruby.

El comportamiento de ubicación que se comparte entre Controladores en un Módulo es, en mi opinión, una buena práctica. Ponerlo en un Helper, por otro lado, es potencialmente engañoso y lo evitaría. Colóquelo en un Módulo "estándar".

4

Ésta es una filosofía pregunta en el mismo nivel que el argumento de que las preguntas el método REST provisto en andamios y si merece la pena tener un andamio. Debe tener en cuenta el hecho de que el libro tutorial de RailsTutorial.org es una guía instructiva de Rails que se levanta y se va. Entonces, para el propósito al que sirve, creo que hace el trabajo.

Sin embargo, ¿hay un lugar mejor para poner el código necesario en los controladores y las vistas? Sí hay.

  • Algunos pueden seguir a Michael Hartl forman Railstutorial e incluyen toda la SessionHelper en los ApplicationController
  • otros pueden decidir exponer sólo los ayudantes esenciales necesarios para la vista, es decir sign_in, 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. Cualquiera que tome puede no importar mucho en rendimiento porque Ruby tendría que analizar el archivo al que desea llamar (o incluir) una clase, módulo o método. Lo que ocurre es que, antes de ejecutar cualquier código en una clase, Ruby pasa por toda la clase una vez para saber qué contiene. Todo depende de lo que uno necesita y el diseño de su aplicación

2

Fwiw, guardo el usuario actual en la clase Usuario:

class User < ActiveRecord::Base 
    cattr_accessor :current 
    ... 
end 

Esto se puede hacer referencia en los 3 niveles MVC; que se establece en el controlador como tal (y del mismo modo el inicio de 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 a nivel de ActiveRecord que capturan el usuario actual (en su caso).

+0

¿Esto crearía un problema de simultaneidad? –

+0

No tengo ningún problema de simultaneidad siempre que User.current esté establecido dentro de ApplicationController. Hubo un tiempo en que me mudé configurando User.current en el archivo del módulo de AuthenticatedSystem en lib, y tuve problemas de concurrencia (posiblemente relacionado con un error en ese código modificado). Revertí sin molestarme en investigar demasiado. Ahora tengo una prueba de integración que comprueba si hay problemas de concurrencia :). –

Cuestiones relacionadas