我遇到了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
感谢。
答案 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开始的代码:逐个调用条件;如果所有条件都匹配,则调用该块。在检查条件和调用块之间没有什么事情发生:它们基本上以相同的上下文运行。