Helper Devise: не удалось найти экземпляр `Warden::Proxy` по запросу

Я пытаюсь использовать Devise для моего приложения на Rails. Я могу зарегистрироваться и войти, но когда я перехожу на другую страницу "build", я получаю следующую ошибку:

Devise:: MissingWarden в 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 ответов

Основываясь на этом SO ответе, вы должны включить Devise::Test::ControllerHelpers модуль в вашем контроллере Добавьте следующее в ваш rails_helper:

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

Это может случиться, когда вы пытаетесь получить Devise current_userв некоторой части кода управляется кабелем действия. например, фоновое задание для рендеринга комментария или чего-то еще. вы можете решить эту проблему, используя что-то вроде следующего в своем контроллере, поскольку вы не можете получить доступ к начальнику на уровне модели или задания (в соответствии с моими ограниченными знаниями): (Я вызываю задание сразу после создания моего комментария в действии создания CommentsController, которое вызывает частный метод для рендеринга частичного комментария, содержащего кнопку редактирования и удаления, для которого требовался 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

это поможет вам решить проблему с надзирателем, если вы использовали в этом партиале devise current_user, он предоставит вам пользователя комментатора (как и должно быть, поскольку этот пользователь инициировал рендеринг партиала). Теперь, чтобы решить эту проблему, если у вас есть интерфейсный фреймворк, вам может потребоваться извлечь текущего пользователя из файлов cookie, чтобы ограничить некоторые действия, такие как редактирование / удаление. но если вы работаете в чистых рельсах, решение, с которым я столкнулся, заключается в том, что вам нужно создать скрытое поле в dom с идентификатором текущего пользователя, и вы получите этот идентификатор для сравнения в скрипте. вам может потребоваться доступ к переменным rails в javascript, для этого вы можете использовать GON gem. Я знаю, что этот ответ может содержать гораздо больше, чем просили, но я много искал и нигде не нашел удовлетворительного решения этой проблемы, не стесняйтесь обсуждать.

Добавлять

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

в вашем файле rails_helper.rb.

У меня была похожая проблема при тестировании представлений, где current_user присутствовал в некоторых условных выражениях.

Я решил это с этим:

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

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

Если у вас возникла эта проблема за пределами Rspec, скажите, что вы пытались отобразить представление в ActionCablechannel, масштабируемый / поддерживаемый подход заключается в использовании помощника или библиотеки представлений, например 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

Что ж, я столкнулся с той же проблемой: "devise не может найти warden:: proxy в actioncable". Это можно решить, передав текущий user_id к вашему методу выполнения в вашей работе, так как вы, возможно, обращаетесь к текущему пользователю в своем представлении, которое вы отображаете с помощью широковещательной передачи, и из-за этой проблемы

Я должен использовать 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

У меня была эта ошибка, и я не мог найти ответ где-либо еще. Это было после падения и создания БД. Но я не загружал схему.

Это исправило это:

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

Я столкнулся с этой ошибкой, когда база данных не была перенесена. Команда ниже сделала свое дело.

./bin/bundle exec rake db:migrate
Другие вопросы по тегам