I've come across the sinatra condition method and am puzzled in how it works.
I have a piece of code:
def auth user
condition do
redirect '/login' unless user_logged_in?
end
end
Which checks to see if a user is logged for certain routes, an example route:
get '/', :auth => :user do
erb :index
end
The method user_logged_in?
is defined in a helper file in the lib directory of the project:
def user_logged_in?
if session[:user]
@user = session[:user]
return @user
end
return nil
end
So, the question is:
How does the condition
block know what the session[:user]
contains, when at the get '/'
route the session[:user]
hasn't even been set?
The condition
method is defined in the following GitHub page: sinatra base condition method
Thanks.
When you define a route, the key of each member of the options hash is called as a method, with the value passed as the arguments.
So when you do get '/', :auth => :user do ...
the method auth
gets called with the argument :user
. This in turn calls the condition
method with the block.
The condition
method is actually defined just above where you link to which is a usage of it. It looks like this:
def condition(name = "#{caller.first[/`.*'/]} condition", &block)
@conditions << generate_method(name, &block)
end
The generate_method
method converts the block into a method with the given name, and then this method is saved in the @conditions
array. The contents of @conditions
are then saved with the definition of the route, and @conditions
is cleared ready for the next route definition.
At this point, the block of code passed to condition
hasn't been executed. It has in effect been saved for later.
When an actual request comes in, if the request path matches the route, then each condition associated with that route is executed to check that it is fulfilled. In this example, this is when redirect '/login' unless user_logged_in?
is first executed, so the session
will have been set up and session[:user]
will be available (or not if they're not logged in).
The important thing to understand about this is that when you pass a block to a method, the code in that block is not necessarily called right away. In this case the code in the block is only called when an actual request arrives.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With