Helper Devise:在请求环境中找不到`Warden :: Proxy`实例

Alp*_*ico 15 ruby ruby-on-rails devise

我尝试使用Devise for my Rails应用程序.我可以注册并登录但是当我转到我的其他页面"构建"时,我收到以下错误:

Devise :: MissingWarden in Home#show Devise Warden::Proxy在您的请求环境中找不到该 实例.确保您的应用程序正在按预期加载Devise和Warden,并且 Warden::Manager中间件存在于您的中间件堆栈中.如果您在其中一个测试中看到这一点,请确保您的测试正在执行Rails中间件堆栈,或者您的测试正在使用Devise::Test::ControllerHelpers模块request.env['warden']为您注入 对象.

这是我的控制器:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  private
  # Overwriting the sign_out redirect path method
  def after_sign_out_path_for(resource_or_scope)
    build_path
  end
end
Run Code Online (Sandbox Code Playgroud)

这是我的两个部分观点:

<!-- views/devise/menu/_login_items.html.erb -->
<% if user_signed_in? %>
  <li>
  <%= link_to('Logout', destroy_user_session_path, :method => :delete) %>
  </li>
<% else %>
  <li>
  <%= link_to('Login', new_user_session_path)  %>
  </li>
<% end %>
Run Code Online (Sandbox Code Playgroud)

<!-- views/devise/menu/_registration_items.html.erb -->
<% if user_signed_in? %>
  <li>
  <%= link_to('Edit registration', edit_user_registration_path) %>
  </li>
<% else %>
  <li>
  <%= link_to('Register', new_user_registration_path)  %>
  </li>
<% end %>
Run Code Online (Sandbox Code Playgroud)

调试之后,我发现问题来自我的"show"控制器中的这一行:template = HomeController.render('layouts/_template')

谢谢你的帮助.

Obr*_*ios 28

基于此SO 答案,您需要将Devise::Test::ControllerHelpers模块包含在控制器规格中.将以下内容添加到rails_helper:

RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, type: :controller
end
Run Code Online (Sandbox Code Playgroud)

  • 当接受的答案与原始问题无关时,我讨厌它。最初的帖子没有提到规格、rspec 或一般测试。这不是正确的答案。 (20认同)

小智 11

当您current_user在由 action cable 管理的代码中调用 Devise 方法(例如 )时,可能会发生这种情况。就像一个后台工作来呈现评论或其他东西。

您可以通过在控制器中执行类似以下操作来解决它。它传播warden到 @env['warden'] 变量,以便 Devise 可以使用它:

def create
  @product = Product.find(comment_params[:product_id])
  @comment = @product.comments.build(comment_params)
  @comment.save!

  gon.comment_id = @comment.id
  gon.comment_user_id = @comment.user_id

  ActionCable.server.broadcast "chat", comment: render_comment
  
  render :create, layout: false
end


def render_comment
  CommentsController.renderer.instance_variable_set(
    :@env, {
      "HTTP_HOST"=>"localhost:3000", 
      "HTTPS"=>"off", 
      "REQUEST_METHOD"=>"GET", 
      "SCRIPT_NAME"=>"",   
      "warden" => warden
    }
  )

  CommentsController.render(
    partial: 'comments/comment_detail',
    locals: {
      product: @product,
      comment: @comment
    }
  )
end
Run Code Online (Sandbox Code Playgroud)

这将帮助您解决监狱长问题,如果您current_user在该部分中使用了 Devise ,它将为您提供评论者用户(因为该用户启动了部分的呈现)。

现在要解决这个问题,如果您有一个前端框架,您可能需要从 cookie 中获取当前用户以限制某些操作,例如编辑/删除。但是如果您在纯 Rails 中工作,我遇到的解决方案是您必须在具有当前用户 ID 的 dom 中创建一个隐藏字段,然后您将获取该 ID 以在脚本中进行比较。您可能需要在 javascript 中访问 rails 变量,为此您可以使用GON gem。

我知道这个答案可能包含的内容比问的要多得多,但我已经搜索了很多,但没有找到满意的解决方案,请随时讨论。


Nee*_*mar 9

添加

config.include Devise::Test::ControllerHelpers, type: :controller
Run Code Online (Sandbox Code Playgroud)

在您的 rails_helper.rb 文件中。

  • 这可能仅适用于 RSpec。 (3认同)

小智 6

在测试某些条件中存在“current_user”的视图时,我遇到了类似的问题。

我用这个解决了它:

let(:user) { FactoryGirl.create :customer }

before(:each) do
  allow(view).to receive(:current_user).and_return(user)
  ...
Run Code Online (Sandbox Code Playgroud)