Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does Sinatra::Base.condition actually do?

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.

like image 352
LJ. Avatar asked Jan 21 '12 13:01

LJ.


1 Answers

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.

like image 137
matt Avatar answered Oct 09 '22 19:10

matt