2012-01-21 13 views
6

Mi sono imbattuto nel metodo sinatra e sono perplesso su come funziona.Cosa fa in realtà Sinatra :: Base.condition?

Ho un pezzo di codice:

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

che controlla per vedere se un utente è connesso per alcune rotte, un percorso esempio:

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

Il metodo user_logged_in? è definito in un aiutante file nella directory lib del progetto:

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

Quindi, la domanda è: In che modo il blocco condition sa cosa contiene session[:user] quando sulla linea get '/' non è stato ancora impostato il session[:user]?

Il metodo condition è definito nella seguente pagina GitHub: sinatra base condition method Grazie.

risposta

4

Quando si definisce un percorso, la chiave di ciascun membro dell'hash delle opzioni è called as a method, with the value passed as the arguments.

Quindi quando si esegue get '/', :auth => :user do ... il metodo auth viene chiamato con l'argomento :user. Questo a sua volta chiama il metodo condition con il blocco.

Il metodo è in realtà conditiondefined just above where you link to che è un utilizzo di esso. Sembra che questo:

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

Il metodo generate_method converte il blocco in un metodo con il nome dato, e quindi questo metodo viene salvato nella matrice @conditions. Il contenuto di @conditions viene quindi salvato con la definizione del percorso e @conditions viene cancellato pronto per la successiva definizione di percorso.

A questo punto, il blocco di codice passato a condition non è stato eseguito. In effetti è stato salvato per dopo.

Quando arriva una richiesta effettiva, se il percorso della richiesta corrisponde alla rotta, quindi each condition associated with that route is executed per verificare che sia soddisfatta. In questo esempio, questo è il momento in cui viene eseguito per la prima volta redirect '/login' unless user_logged_in?, quindi session sarà impostato e session[:user] sarà disponibile (o meno se non sono stati registrati).

La cosa importante da capire su questo è che quando si passa un blocco a un metodo, il codice in quel blocco non viene necessariamente chiamato immediatamente.In questo caso il codice nel blocco viene chiamato solo quando arriva una richiesta effettiva.

+0

grazie mille per una spiegazione accurata. Le mie capacità di lettura di Ruby sono state totalmente messe da parte quando ho osservato il metodo 'condition'. Anche se leggere il codice mi sembra ancora abbastanza doloroso, mi hai permesso di capire che cosa sta succedendo. Saluti. –

2

Poiché Sinatra è responsabile della chiamata sia dei metodi della condizione che dei metodi del percorso. Pertanto, dovrebbe essere sicuro di presumere che qualsiasi cosa sia impostata quando viene eseguito il metodo di instradamento viene impostata anche quando la condizione viene eseguita.

Dai un'occhiata al codice che inizia here: le condizioni sono chiamate una per una; se tutte le condizioni corrispondono, viene chiamato il blocco. Non succede molto tra il controllo delle condizioni e la chiamata del blocco: sono fondamentalmente eseguiti con lo stesso contesto.

+0

Grazie per questo, @matt è stato in grado di mostrare cosa sta succedendo nel contesto del mio programma, che è quello che cercavo. –