Helper Devise:在请求环境

时间:2017-01-28 14:08:02

标签: ruby-on-rails ruby devise

我尝试将Devise用于我的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

这是我的两个部分观点:

<!-- 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 %>

<!-- 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 %>

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

感谢您的帮助。

9 个答案:

答案 0 :(得分:21)

根据此SO answer,您需要在控制器规范中包含Devise::Test::ControllerHelpers模块。将以下内容添加到rails_helper:

RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, type: :controller
end

答案 1 :(得分:3)

添加

config.include Devise::Test::ControllerHelpers, type: :controller

在rails_helper.rb文件中。

答案 2 :(得分:1)

我遇到此错误,在其他任何地方都找不到答案。是在删除并创建数据库之后。但是我没有加载架构。

此问题已解决:

rake db:drop db:create db:schema:load

答案 3 :(得分:1)

我必须在 helper 方法中使用 current_user,因为我正在编写规范。

let(:user) { create(:user) }
before do
 allow(helper).to receive(:current_user).and_return(user)
end

但如果您正在处理视图规范,请执行此操作

let(:user) { create(:user) }
before do
 allow(view).to receive(:current_user).and_return(user)
end

答案 4 :(得分:0)

好吧,我遇到了同样的问题“设备无法在actioncable中找到看守::代理”,可以通过将当前的user_id传递给工作中的perform方法来解决,因为您可能正在访问您认为通过广播呈现的当前用户,并且是由于此问题引起的

答案 5 :(得分:0)

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

我用以下方法解决了它:

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

before(:each) do
  allow(view).to receive(:current_user).and_return(user)
  ...

答案 6 :(得分:0)

未迁移数据库时遇到此错误。下面的命令可以解决问题。

./bin/bundle exec rake db:migrate

答案 7 :(得分:0)

当您尝试通过动作电缆管理某些代码中的Devise current_user时,可能会发生这种情况。例如后台作业以呈现评论或其他内容。 您可以通过在控制器中使用以下操作来解决此问题,因为您无法在模型或工作级别访问守望者(根据我的有限知识): (我在CommentsController create操作中创建评论后立即调用作业,该操作调用一个私有方法来呈现一个包含edit和delete按钮的评论部分,为此需要current_user)

 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

这将帮助您解决管理员问题,如果您在该partial中使用了devise的current_user,它将为您提供注释者用户(因为该用户启动了partial的呈现,所以应该如此)。 现在解决此问题,如果您有一个前端框架,则可能需要从cookie中获取当前用户,以限制某些操作,例如编辑/删除。但是,如果您使用的是纯轨,则遇到的解决方案是您必须在具有当前用户ID的dom中创建一个隐藏字段,并且您将获取该ID以在脚本中进行比较。您可能需要使用javascript访问rails变量,因此可以使用 GON gem。 我知道这个答案可能包含的内容远远超出了询问的范围,但是我进行了很多搜索,没有找到一个令人满意的解决方案,请随时讨论。

答案 8 :(得分:0)

如果您在Rspec之外遇到此问题,则表示您试图在ActionCable通道内渲染视图,可伸缩/可维护的方法是使用助手或类似ViewComponents /的视图库cells。这样,您可以将现有视图提取到组件中,并参数化视图中调用的所有devise / warden方法。这种方法的优点是

  1. 该视图更易于测试
  2. 您可以在代码中的任何地方调用它
  3. 没有耦合的依赖项

使用视图助手的示例

app/views/messages/show.html.erb中有以下内容

<%= current_user.first_name %>
<%= @message %>

在控制器外部调用MessagesController.render :show会导致错误,因为无法访问请求对象。使用ViewComponents,我们将视图提取到其自己的组件中

app/components/message_component.rb

class MessageComponent < ViewComponent::Base
  def initialize(user:, message:)
    @user = user
    @message = message
  end
end

app/components/message_component.html.erb

<%= @user.first_name %>
<%= @message %>

用法

app/views/messages/show.html.erb中只需致电

<%= render(MessageComponent.new(message: @message, user: current_user) %>

在ActionCable中,这样称呼

ApplicationController.render(MessageComponent.new(message: @message, user: current_user)

由于您可以从代码中的任何地方访问ActiveRecord模型,因此您应该能够获取@message