在Rails中使用Turbo Stream进行多次部分更新

huangapple go评论62阅读模式
英文:

Multiple Partial Updates in Rails using Turbo Stream

问题

我有两个模型,一个是客户,另一个是投诉,一个客户可能有多个投诉。如果要将投诉添加到客户中,如何使用 Turbo Stream 来更新投诉的索引和客户的展示视图,同时使用两个不同的局部视图,确保只列出特定客户的投诉在客户展示视图中?

以下是我的一些代码:

客户模型:

class Customer < ApplicationRecord
  validates_presence_of :names
  belongs_to :company
  has_many :complaints

  broadcasts_to ->(customer) { [customer.company, "customers"] }, inserts_by: :prepend
end

投诉模型:

class Complaint < ApplicationRecord
  belongs_to :company
  belongs_to :customer

  broadcasts_to ->(complaint) { [complaint.company, "complaints"] }, inserts_by: :prepend
end

投诉索引页面(正常流式显示):

<%= turbo_stream_from @company, "complaints" %>

<h1>Complaints</h1>

<%= link_to new_complaint_path, class: "btn", data: { turbo_frame: "remote_modal" } do %>
  New
<% end %>
<div class="table-responsive">
  <table class="table">
    <thead>
      <tr>
        <th scope="col">Customer</th>
        <th scope="col">Date</th>
        <th scope="col">Note</th>
        <th colspan="2"></th>
      </tr>
    </thead>
    <tbody id="complaints">
      <%= render @complaints %>
    </tbody>
  </table>
</div>

客户展示视图(不流式显示):

<%= turbo_stream_from @customer %>
<%= turbo_stream_from @customer, "complaints" %>

<%= turbo_frame_tag "customer" do %>
  <%= @customer.names %>
<% end %>

<%= link_to edit_employee_path(@customer), class: "btn", data: { turbo_frame: "remote_modal" } do %>
  Edit
<% end %>

<h4>Complaints</h4>

<%= link_to new_complaint_path, class: "btn", data: { turbo_frame: "remote_modal" } do %>
  Add
<% end %>

<div class="table-responsive">
  <table class="table">
    <thead>
      <tr>
        <th scope="col">Date</th>
        <th scope="col">Note</th>
        <th colspan="2"></th>
      </tr>
    </thead>
    <tbody id="complaints">
      <%= render @complaints %>
    </tbody>
  </table>
</div>
英文:

I have two models, one for customer and one for complaints, one customer also has many complaints. If a complaint is added to the customer, how can you use Turbo Stream to update both the index of complaints and the show view of the customer using two different partials while ensuring only the specific customer's complaints are listed in the customer show view?

Here is some of my code:

Customer model:

class Customer &lt; ApplicationRecord
    validates_presence_of :names
    belongs_to :company
    has_many :complaints

    broadcasts_to -&gt;(customer) { [customer.company, &quot;customers&quot;] }, inserts_by: :prepend
end

Complaint model:

class Complaint &lt; ApplicationRecord
    belongs_to :company
    belongs_to :customer

    broadcasts_to -&gt;(complaint) { [transgression.company, &quot;complaints&quot;] }, inserts_by: :prepend
end

Complaints index.html.erb (streaming fine):

&lt;%= turbo_stream_from @company, &quot;complaints&quot; %&gt;

&lt;h1&gt;Complaints&lt;/h1&gt;


&lt;%= link_to new_complaint_path, class: &quot;btn&quot;, data: { turbo_frame: &quot;remote_modal&quot; } do %&gt;
  New
&lt;% end %&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
  &lt;table class=&quot;table&quot;&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th scope=&quot;col&quot;&gt;Customer&lt;/th&gt;
        &lt;th scope=&quot;col&quot;&gt;Date&lt;/th&gt;
        &lt;th scope=&quot;col&quot;&gt;Note&lt;/th&gt;
        &lt;th colspan=&quot;2&quot;&gt;&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody id=&quot;complaints&quot;&gt;
      &lt;%= render @complaints %&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

Customer show.html.erb view (not streaming...):

&lt;%= turbo_stream_from @customer %&gt;
&lt;%= turbo_stream_from @customer, &quot;complaints&quot; %&gt;

  &lt;%= turbo_frame_tag &quot;customer&quot; do %&gt;
    &lt;%= @customer.names %&gt;
  &lt;% end %&gt;

  &lt;%= link_to edit_employee_path(@customer), :class =&gt; &quot;btn&quot;, data: { turbo_frame: &quot;remote_modal&quot; } do %&gt;
    Edit
  &lt;% end %&gt;

  &lt;h4&gt;Complaints&lt;/h4&gt;

  &lt;%= link_to new_complaint_path, class: &quot;btn&quot;, data: { turbo_frame: &quot;remote_modal&quot; } do %&gt;
    Add
  &lt;% end %&gt;

  &lt;div class=&quot;table-responsive&quot;&gt;
    &lt;table class=&quot;table&quot;&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;Date&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;Note&lt;/th&gt;
          &lt;th colspan=&quot;2&quot;&gt;&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody id=&quot;complaints&quot;&gt;
        &lt;%= render @complaints %&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

答案1

得分: 1

在客户展示页面上,您正在订阅@customer, "complaints",但您没有向其广播任何内容,因此没有更新。

# app/models/complaint.rb

class Complaint &lt; ApplicationRecord
    belongs_to :company
    belongs_to :customer

    # 注意:这将发送 turbo 流到`[company, "complaints"]`
    #       您必须订阅该通道以接收更新。
    # 默认值:
    #       部分: "complaints/complaint"
    #       目标:  "complaints"
    broadcasts_to -&gt;(complaint) { [complaint.company, "complaints"] }, inserts_by: :prepend

    # 注意:要在客户展示页面上接收更新,您必须发送更新到[customer, "complaints"]
    broadcasts_to -&gt;(complaint) { [complaint.customer, "complaints"] },
      inserts_by: :prepend,
      partial: "customers/complaint" # <= 如果您想使用不同的部分
end
# app/views/customers/show.html.erb

# 确保订阅您正在广播的通道
&lt;%= turbo_stream_from @customer, "complaints" %&gt;

# 对于传入的 turbo 流,您必须有一个 `id` 目标
&lt;div id="complaints"&gt;
  # 渲染不同的部分
  &lt;%= render partial: "customers/complaint", collection: @complaints %&gt;
&lt;/div&gt;

我不确定您在控制器中有什么问题,您无需为广播执行任何操作:

# app/controllers/customers_controller.rb

# GET /customers/1
def show
  # 注意:仅在初始请求上显示特定客户的投诉
  #       广播已经限制为`@customer`
  @complaints = @customer.complaints
end
英文:

On customer show page you're subscribing to @customer, &quot;complaints&quot; but you're not broadcasting anything to it, so there are no updates.

# app/models/complaint.rb

class Complaint &lt; ApplicationRecord
    belongs_to :company
    belongs_to :customer

    # NOTE: this will send turbo streams to `[company, &quot;complaints&quot;]`
    #       you have to be subscribed to that channel to receive updates.
    # Defaults:
    #       partial: &quot;complaints/complaint&quot;
    #       target:  &quot;complaints&quot;
    broadcasts_to -&gt;(complaint) { [complaint.company, &quot;complaints&quot;] }, inserts_by: :prepend

    # NOTE: to receive updates on the customer show page you have send
    #       updates to [customer, &quot;complaints&quot;]
    broadcasts_to -&gt;(complaint) { [complaint.customer, &quot;complaints&quot;] },
      inserts_by: :prepend,
      partial: &quot;customers/complaint&quot; # &lt;= if you want to use a different partial
end
# app/views/customers/show.html.erb

# make sure to subscribe to a channel that you&#39;re broadcasting to
&lt;%= turbo_stream_from @customer, &quot;complaints&quot; %&gt;

# you have to have an `id` target for the incoming `turbo_stream`
&lt;div id=&quot;complaints&quot;&gt;
  # render a different partial
  &lt;%= render partial: &quot;customers/complaint&quot;, collection: @complaints %&gt;
&lt;/div&gt;

I'm not sure what issues you have in the controllers, you don't need to do anything for broadcasts to work:

# app/controllers/customers_controller.rb

# GET /customers/1
def show
  # NOTE: only show specific customer complaints on initial request
  #       broadcasts are already limited to `@customer`
  @complaints = @customer.complaints
end

huangapple
  • 本文由 发表于 2023年2月8日 20:50:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75386060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定