我遇到了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目录中的helper文件中定义的:
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
谢谢。

最佳答案

定义路由时,options散列的每个成员的键都是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]将可用(如果它们未登录,则不可用)。
了解这一点的重要一点是,当您将一个块传递给一个方法时,该块中的代码不一定立即被调用。在这种情况下,块中的代码只在实际请求到达时调用。

07-24 19:25
查看更多