【问题标题】:ActionCable + Devise + Pundit + ApplicationController.renderActionCable + Devise + Pundit + ApplicationController.render
【发布时间】:2016-11-16 20:14:01
【问题描述】:

我正在尝试在 ActionJob 中呈现模板以通过 ActionCable 进行广播。

ApplicationController.render(partial: "messages/message", locals: { message: message }, assigns: { current_user: user}).squish

在大多数情况下,这可以正常工作,但是我的一些模板在视图中使用 Punit 进行授权。

<% if policy(message).show? %>
  <%= message.body %>
<% end %>

这会在作业运行时引发错误。

ActionView::Template::Error: Devise could not find the `Warden::Proxy` instance on your request environment.

快速谷歌搜索发现这个问题:https://github.com/plataformatec/devise/issues/4271

票证和链接中提到,没有可用的 env['warden'] 因为没有执行中间件来添加它。

我该如何解决这个问题?

【问题讨论】:

  • 你检查this了吗?
  • @ArunKumar 是的,这是票证中引用的链接之一。

标签: ruby-on-rails devise pundit actioncable


【解决方案1】:

作为一种解决方法,这就是我所做的:

class ActiveJobController < ActionController::Base
end

在我的部分中,我不使用 policy 助手,而是这样做

<% if Pundit::PolicyFinder.new(message).policy.new(current_user, message).show? %>
  <%= message.body %>
<% end %>

来自我的ActiveJob

ActiveJobController.render(partial: "messages/message", locals: { message: message, current_user: user }).squish

这避免了任何引用 env["warden"] 的股票 Devise 和 Pundit 助手。它并不理想,但现在在请求和作业中呈现时都适用。

【讨论】:

  • 你拯救了我的一天。非常感谢。
【解决方案2】:

另一种可扩展/可维护的方法是使用帮助程序或视图库,例如 ViewComponents/cells。这样,您可以将现有视图提取到组件中,并参数化视图中调用的任何设计/管理员方法。这种方法的优点是

  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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    相关资源
    最近更新 更多