在 Hotwire 局部视图中使用 current_user

3

你好,我开始在Rails应用程序中使用Hotwire(目前正在添加评论),发现Turbo Streaming使用的局部文件没有全局引用,但是我想在局部文件中使用current_user,但是这样就必须重新加载页面才能添加评论。你们有没有遇到过类似的问题?可以给我一些提示吗?


1
你可以通过传递一个locals哈希表将参数传递给一个局部视图(包括Turbo流式局部视图)。所以像这样:<%= turbo_stream.replace "foo", partial: "my_partial", locals: {user: current_user } %> 将会把当前用户作为user参数传递给局部视图。 - undefined
2个回答

4

我会提供详细的回答,因为这正是我在不知道答案时希望找到的。以下是解释:

使用Current.user而不是user current_user。具体操作如下:

  1. 创建一个名为Current的模型。请注意,此模型不是从ApplicationRecord继承的,而是从ActiveSupport::CurrentAttributes继承的。在Rails文档中此处了解更多信息。
app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
  attribute :user
end
  1. 将当前用户设置为ApplicationController中Current的用户属性
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_current_user, if: :user_signed_in?

  private

  def set_current_user
    Current.user = current_user
  end
end
  1. 现在,在你的partials中,删除所有对current_user的调用,并使用本地变量。因此,如果你有current_user.posts,则使用user.posts。在任何需要使用current_user的partial中(该partial嵌套在需要使用Turbo Streams的视图中),仅使用本地变量,并从你的视图中传递:

    user: Current.user。

在我的情况下,我需要在我的Roles上使用Turbo Streams,但我需要将当前用户传递给我的roles/_role partial,所以:

app/views/roles/index.html.erb
<%= turbo_stream_from "roles" %>

<%= turbo_frame_tag "roles" do %>
  <% @roles.each do |role| %>
    <%= render "roles/role", role: role, user: Current.user %>
  <% end %>
<% end %>
app/views/roles/_role.html.erb
<%= turbo_frame_tag role do %>
  <div class="role">
    <%# Some stuff %>
    <%= render "opportunities/form", role: role, user: user %>
    <%# Some stuff %>
  </div>
<% end %>
app/views/opportunities/_form.html.erb
<% if user.opportunities.find_by(role_id: role.id) %>
  <%# Some stuff %>
<% end %>

请注意,在局部模板中我只使用“user”(本地变量),而从我的视图中,我向下传递user: Current.user

  1. 现在,在你想要使用turbo_streams的模型中,你需要手动设置每个你想要定位的操作。以下是我所做的:
app/models/role.rb
after_create_commit  -> { broadcast_prepend_later_to "roles", partial: "roles/role", locals: { role: self, user: Current.user }, target: "roles" }
after_update_commit  -> { broadcast_replace_later_to "roles", locals: { role: self, user: Current.user } }
after_destroy_commit -> { broadcast_remove_to "roles" }

为了完整起见:

这是我的控制器(仅包含我们需要的操作):

app/controllers/roles_controller.rb
class RolesController < ApplicationController
  def create
    @role = Role.new(role_params)
    
    if @role.save
      respond_to do |format|
        format.html { redirect_to roles_path, notice: "Role created." }
        format.turbo_stream
      end
    else
      render :new, status: :unprocessable_entity
    end
  end

  def update
    @role = Role.find(params[:id])

    if @role.update(role_params)
      respond_to do |format|
        format.html { redirect_to roles_path, notice: "Role updated." }
        format.turbo_stream
      end
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @role = Role.find(params[:id])
    @role.destroy
    respond_to do |format|
      format.html { redirect_to roles_path, notice: "Role deleted." }
      format.turbo_stream
    end
  end
end

我可以帮您翻译,以下是翻译结果:

app/views/roles/create.turbo_stream.erb

我的 turbo_stream 视图:

<%= turbo_stream.prepend "roles", partial: "roles/role", locals: { role: @role, user: Current.user } %>
app/views/roles/destroy.turbo_stream.erb
<%= turbo_stream.remove @role %>

我希望这能有所帮助。

0

在session_controller中将current_user_id保存到cookies中

cookies[:current_user_id] = current_user.id

在这里输入图像描述

在application_controller中

def devise_current_user
 @devise_current_user ||= warden.authenticate(scope: :user)
end

def current_user
  devise_current_user
  rescue
    User.find(cookies[:current_user_id])
end

这并没有回答问题。一旦你拥有足够的声望,你就可以评论任何帖子;相反,提供不需要提问者澄清的答案。- 来自审核 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接