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, скажите, что вы пытались отобразить представление в
ActionCable
channel, масштабируемый / поддерживаемый подход заключается в использовании помощника или библиотеки представлений, например ViewComponents/cells. Таким образом, вы можете извлечь существующее представление в компонент и параметризовать любые методы devise / warden, вызываемые в представлении. Преимущество такого подхода:
- Вид легче проверить
- Вы можете вызвать его из любого места вашего кода
- Нет парных зависимостей
Пример использования помощников просмотра
Скажите, что у вас есть
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