这个传递给 Devise 的认证方法的 lambda 函数是如何工作的?

How does this lambda function passed to Devise's authenticated method work?

this问题中,@user2205763建议使用lambda函数:

authenticated :user, lambda {|u| u.is_test } do
    // route stuff here
end

我假设它以某种方式将 :user 变成一个实际的 Devise User 对象 (u) 但它是如何做到的 - 它实际上在做什么?

Rails 允许基于路由定义中使用 constraints 的一组规则来约束路由。请参阅 API 文档中的 Dynamic request matching 示例。

Devise 在其 authenticated 方法中使用了它。来源是 here.

authenticated 方法如下所示:

def authenticated(scope=nil, block=nil)
  constraints_for(:authenticate?, scope, block) do
    yield
  end
end

正在调用 constraints_for:

def constraints_for(method_to_apply, scope=nil, block=nil)
  constraint = lambda do |request|
    request.env['warden'].send(method_to_apply, scope: scope) &&
      (block.nil? || block.call(request.env["warden"].user(scope)))
  end

  constraints(constraint) do
    yield
  end
end 

所以 scope:user 并且 method_to_apply:authenticate? 并且 request.env["warden"] 是一个允许您检查身份验证的对象 injected into the environment by Warden .

这意味着 constraint = ... 正在创建一个调用 authenticate? 的 lambda,然后调用您的块,例如|u| u.is_test u 设置为 request.env["warden"].user 的结果(即调用 authenticate? 之后的当前用户)

然后将该 lambda 作为匹配 constraints 的动态请求传递,进而产生 // route stuff here 所在的块!