2012-01-21 13 views
6

Me he encontrado con el sinatra condición método y estoy perplejo en la forma en que funciona.¿Qué hace Sinatra :: Base.condition en realidad?

I tienen una pieza de código:

def auth user 
    condition do 
    redirect '/login' unless user_logged_in? 
    end 
end 

que comprueba si un usuario se registra para ciertas rutas, un ejemplo de ruta:

get '/', :auth => :user do 
    erb :index 
end 

El método user_logged_in? se define en un ayudante archivo en el directorio lib del proyecto:

def user_logged_in? 
    if session[:user] 
    @user = session[:user] 
    return @user 
    end 
    return nil 
end 

Entonces, la pregunta es: ¿Cómo sabe el bloque condition qué contiene el session[:user], cuando en la ruta get '/' el session[:user] ni siquiera se ha configurado?

El método condition se define en la siguiente página de GitHub: sinatra base condition method Gracias.

Respuesta

4

Cuando define una ruta, la clave de cada miembro del hash de opciones es called as a method, with the value passed as the arguments.

Entonces cuando haces get '/', :auth => :user do ... se llama al método auth con el argumento :user. Esto a su vez llama al método condition con el bloque.

El método condition es en realidad defined just above where you link to que es un uso de ella. Parece que este:

def condition(name = "#{caller.first[/`.*'/]} condition", &block) 
    @conditions << generate_method(name, &block) 
end 

El método generate_method convierte el bloque en un método con el nombre dado, y entonces este método se guarda en la matriz @conditions. El contenido de @conditions se guarda con la definición de la ruta y @conditions se borra listo para la siguiente definición de ruta.

En este punto, el bloque de código pasado a condition no se ha ejecutado. En efecto, se ha guardado para más adelante.

Cuando entra una solicitud real, si la ruta de solicitud coincide con la ruta, entonces each condition associated with that route is executed para verificar que se cumpla. En este ejemplo, esto es cuando se ejecuta por primera vez redirect '/login' unless user_logged_in?, por lo que se habrá configurado session y session[:user] estará disponible (o no si no han iniciado sesión).

Lo importante a tener en cuenta al respecto es que cuando pasa un bloque a un método, el código en ese bloque no se llama necesariamente de inmediato.En este caso, el código en el bloque solo se invoca cuando llega una solicitud real.

+0

muchas gracias por una explicación cuidadosa. Mis habilidades de lectura de Ruby estaban totalmente perplejas cuando miré el método 'condición '. Aunque leer el código todavía se siente bastante doloroso, me has permitido entender qué está sucediendo. Aclamaciones. –

2

Porque Sinatra es responsable de llamar tanto a los métodos de condición como a los métodos de ruta. Por lo tanto, debe ser seguro suponer que lo que esté establecido cuando se ejecuta el método de ruta también se establece cuando se ejecuta su condición.

Eche un vistazo al código que comienza here: las condiciones se llaman una por una; si todas las condiciones coinciden, se llama al bloque. No ocurre mucho entre las condiciones de control y la llamada al bloque: básicamente se ejecutan con el mismo contexto.

+0

Gracias por esto, @matt pudo mostrar lo que está sucediendo dentro del contexto de mi programa, que es lo que estaba buscando. –

Cuestiones relacionadas