【问题标题】:Rails Devise current_user is undefined in a matches? advanced route constraintRails Devise current_user 在匹配项中未定义?高级路由约束
【发布时间】:2015-06-01 13:35:33
【问题描述】:

当我尝试在 ma​​tches? 约束中使用 current_user 时,我收到错误 NameError (undefined local variable or method "current_user" for #<APIRouter:0x007ffd54a81f98>):。我希望某些虚拟用户被路由到一组控制器,而其他用户被路由到另一组控制器。但是,当我尝试使用 current_user 时出现错误。

  • 设计 (2.0.4)
  • 导轨 (3.2.2)

我的匹配约束在 APIRouter 类中定义:

class APIRouter
  def matches? request
    @use_rm_app = ENV["USE_RM_APP"] == "true" || (current_user && current_user.is_test)
  end
end

关于如何在比赛中使用当前用户有什么想法吗? Rails guide 中定义的约束。

来自 routes.rb 文件的部分:

#  Route to the rm_app controller if APIRouter says we should, otherwise use the real backend controllers.
match '/api/v1/*path', :controller => 'api/v1', 
  :action => 'handle_create_request', 
  :via => :post, :constraints => APIRouter.new

更新:感谢 ksol。 尝试 3 有效。获取用户使用request.env["warden"].user(:user)

解决办法是修改APIRouter

  def matches? request
    user = request.env["warden"].user(:user)
    (user && user.is_test) || ENV["USE_RM_APP"] == "true"
  end

【问题讨论】:

    标签: ruby-on-rails devise


    【解决方案1】:

    current_user 仅在您的控制器和视图中可用。有不止一种方法可以实现您想要的,更容易将其作为参数提供给您的方法。

    编辑

    如果current_user 在路由器中可访问,您可以通过执行constraints: APIRouter.new(current_user) 将其传递给您的约束类。然后您需要定义APIRouter#initialize 并将current_user 存储在一个实例变量中,您可以在matches? 中使用该变量。

    编辑 2

    我只记得设计允许您在路由器中执行此操作:

    authenticated :user do
      root :to => "main#dashboard"
    end
    

    我不知道如何确保user.is_test

    编辑 3

    最后一次尝试。 request.env["warden"].user(:user) 应该给你一个用户,如果一个经过身份验证。

    【讨论】:

    • 感谢您的回复。然而,比赛呢?调用是由 rails 直接基于路由文件中指定的约束进行的。由于我不拨打电话,因此无法传入 current_user。我可以将当​​前用户隐藏在全局线程中,但这似乎是个坏主意。还有其他想法吗?
    • 试过了。不工作。 current_user 未在 routes.rb 的上下文中定义。此外,约束类在启动时被实例化一次,因此这种方法不会奏效。
    • block in <top (required)>': undefined local variable or method "current_user" for #<ActionDispatch::Routing::Mapper:0x007f8cfef9e8a8> (NameError)
    • is_test 只是来自我的用户模型。如果我可以访问 current_user,那么我的 User 模型已经定义了 is_test。我将查看已验证但 :user 只是一个符号而不是真正的用户对象。
    • 哇!似乎工作!让我再测试一下,然后我会更新帖子
    【解决方案2】:

    基于 ksol 的帖子,您可以通过将块传递给经过身份验证的用户来确保 user.is_test:

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

    这是假设 u.is_test 返回一个布尔值。

    【讨论】:

    • 通常我会避免在路由文件中使用当前用户,但我发现在一些场景中,在路由层处理特定于用户的重定向而不是传播它会少很多痛苦跨控制器。这种 lambda 方法是迄今为止最干净的解决方案。
    【解决方案3】:

    只要记住添加 diff :as for both root 否则会出错

    authenticated :user do
      root :to => "main#dashboard", :as => :foo
    end
    
    root :to => "main#landing_page"
    

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-29
      • 1970-01-01
      • 2016-09-13
      相关资源
      最近更新 更多