Sinatra :: Base.condition实际上做了什么?

时间:2012-01-21 13:41:38

标签: ruby session sinatra block

我遇到了sinatra 条件方法,并对它是如何工作感到困惑。

我有一段代码:

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

检查用户是否记录了某些路由,例如路线:

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

方法user_logged_in?在项目的lib目录中的帮助文件中定义:

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

所以,问题是: condition块如何知道session[:user]包含哪些内容,在get '/'路由时session[:user]尚未设置?

condition方法在以下GitHub页面中定义:sinatra base condition method 感谢。

2 个答案:

答案 0 :(得分:4)

定义路由时,选项哈希的每个成员的键是called as a method, with the value passed as the arguments

因此,当您执行get '/', :auth => :user do ...时,将使用参数auth调用方法:user。这反过来用块调用condition方法。

condition方法实际上是defined just above where you link to,它是用法。它看起来像这样:

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

generate_method方法将块转换为具有给定名称的方法,然后将此方法保存在@conditions数组中。然后使用路由定义保存@conditions的内容,并为下一个路由定义准备好@conditions

此时,传递给condition的代码块尚未执行。它实际上已保存以供日后使用。

当实际请求进入时,如果请求路径与路由匹配,则each condition associated with that route is executed检查它是否已满足。在此示例中,这是首次执行redirect '/login' unless user_logged_in?时,因此session已设置且session[:user]可用(如果未登录,则为{{1}}。< / p>

要理解这一点的重要一点是,当您将块传递给方法时,该块中的代码不一定立即被调用。在这种情况下,块中的代码仅在实际请求到达时被调用。

答案 1 :(得分:2)

因为Sinatra负责调用条件方法和路由方法。因此,应该可以安全地假设,当您的条件执行时,也会设置路由方法执行时设置的内容。

看一下从here开始的代码:逐个调用条件;如果所有条件都匹配,则调用该块。在检查条件和调用块之间没有什么事情发生:它们基本上以相同的上下文运行。