2011-07-10 17 views
6

Estoy intentando crear un sistema "solo haga clic en su nombre para iniciar sesión" utilizando auth_logic. Mi modelo de usuario tiene un campo de correo electrónico y nombre. Para iniciar sesión, simplemente lo hago:# <UserSession: {: unuthorized_record => "<protected>"}>

UserSession.create(@user, true) 

Lamentablemente, eso no da como resultado que se cree una sesión. El uso de un depurador que encontré este mensaje:

#<UserSession: {:unauthorized_record=>"<protected>"}> 

Mi modelo usuario sólo tiene una línea:

acts_as_authentic 

línea de sesión de usuario tiene esto, que he encontrado en alguna parte. No estoy seguro de lo que hace y lo he intentado con y sin:

class UserSession < Authlogic::Session::Base 
    def to_key 
    new_record? ? nil : [ self.send(self.class.primary_key) ] 
    end 
end 

La base de datos (tampoco estoy seguro de si es necesaria esa mesa user_sessions):

create_table "sessions", :force => true do |t| 
    t.string "session_id", :null => false 
    t.text  "data" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" 
add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" 

create_table "user_sessions", :force => true do |t| 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

create_table "users", :force => true do |t| 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.string "persistence_token" 
    t.string "email" 
    t.string "name" 
end 

I' m usando Rails 3.0.9 y mi Gemfile dice (he intentado tanto la normal y la gema authlogic Github):

gem 'rails', '3.0.9' 
gem 'sqlite3' 
gem "authlogic" #, :git => 'git://github.com/odorcicd/authlogic.git', :branch => 'rails3' 

Here 's el resto del código fuente.

Tuve este problema hace unos días en un proyecto similar y "simplemente se fue" en algún momento. Simplemente no recuerdo cómo.

¿Alguna idea? Esto me está volviendo loco ...

+0

Hola Sjors, estoy teniendo el mismo problema. ¿Encontraste una solución a este problema? – Dorian

+0

@dorian si solo necesitas iniciar sesión en Twitter, esta joya lo hace trivial: https://github.com/mislav/twitter-login –

+0

También con el mismo problema. ¿Alguna solución? –

Respuesta

2

Solución posible ... parece que hay dos versiones de esos ejemplos de métodos de ayuda que flotan. Existe la one que utilizamos:

@current_user = current_user_session && current_user_session.user 

y luego está the newer version que se encuentra en algunos tutoriales y ejemplos más recientes:

@current_user = current_user_session && current_user_session.record 

Al parecer, cuando .user (o cualquiera que sea el campo de inicio de sesión es) está llamado en el objeto de sesión, devuelve el registro no autorizado, mientras que .record.user devuelve los datos apropiados.

+0

Gracias, me cambié a usar la gema twitter-login hace un tiempo, así que no puedo probar su solución. Estoy seguro de que será de ayuda para alguien. –

1

Experimenté este problema recientemente y me confundí también. He descubierto el problema específico de mi código, por lo que esta es otra posible solución.

tl; dr

No entendía que #<UserSession: {:unauthorized_record=>"<protected>"}> sigue siendo válida la sesión de usuario, sólo un uno unauthed que hemos creado nosotros mismos. Puede confirmarlo llamando al user y obtendrá la instancia User que haya pasado al UserSession.create.

Causa

El problema real es dos veces. El método current_user se creó con la suposición de que el usuario actual no cambiaría durante la vigencia de una solicitud y Estaba llamando al current_user antes de crear uno para asegurarse de que no tenía uno.Se puede simplificar a la siguiente:

def current_user 
    return @current_user if defined?(@current_user) 

    @current_user = some_method_that_finds_a_proper_user 
end 

La clave aquí es que mi método para encontrar un usuario puede volver nil. Cuando lo haga, definirá @current_user como nil y, por lo tanto, ese valor almacenado en caché siempre se devolverá en llamadas posteriores.

Soluciones

Aquí es donde se pone un poco más difícil, ya que realmente depende de lo que necesita su código.

  1. Si no necesita el current_user después de firmar un modelo de usuario con UserSession.create entonces no es necesario hacer nada más que esperar a que el render o redirigir. En su próxima solicitud, su current_user se configurará correctamente.

  2. Si no es necesario comprobar si hay un usuario ya conectado, retire cualquier llamada a current_user antes UserSession.create y si es capaz de la primera llamada a current_user funcionará como se espera.

  3. asegurar que su cadena de método que produce current_user o bien no utilizar el almacenamiento en caché, no almacenar en caché nil s, o cambiar el protector de estos valores almacenados en caché para determinar si el valor es Truthy en lugar de si se ha definido la variable de instancia. El guardia podría ser cambiado a:

    return @current_user if [email protected]_user.nil? # or @current_user.present? in Rails 
    

    o puede utilizar retorno ||= operador e implícito de Ruby. Mi ejemplo simplificado anterior podría ser en su lugar:

    def current_user 
        @current_user ||= some_method_that_finds_a_proper_user 
    end 
    

    o si no es tan simple

    def current_user 
        @current_user ||= begin 
        some_code 
        doing_many 
        things_here 
        end 
    end 
    
  4. O su problema podría ser que usted está teniendo problemas para escribir una prueba para este comportamiento. En ese caso, prefiero sólo hay que poner una expectativa en el código como

    expect(UserSession).to receive(:create).with(user) 
    
Cuestiones relacionadas