Rails - 如何通过表单拆分嵌套的属性?

Rails - How to split nested attributes through the form?

我知道我们可以使用 fields_for 为嵌套属性创建字段子部分。但是,我想通过表格将它们分开。我该怎么做?

例如:

假设我有一个带有嵌套条形图模型的模型 foo,如下所示:

class Foo < ApplicationRecord
  has_many :bars
  accepts_nested_attributes_for :bars
end

一般的观点是这样的:

<%= form_for @foo do |f| %>
  <!-- foo fields -->

  <%= f.fields_for :bars do |f_bar| %>
    <!-- bar fields -->
  <% end %>

  <%= f.submit "Submit" %>
<% end %>

但出于美观原因,我不希望所有 bars 聚集在一个地方。我想做类似的事情:

<%= form_for @foo do |f| %>
  <!-- foo fields -->

  <%= f.fields_for :bars do |f_bar| %>
    <!-- bar fields of one bar -->
  <% end %>

  <!-- other foo fields -->

  <%= f.fields_for :bars do |f_bar| %>
    <!-- bar fields of another bar -->
  <% end %>

  <!-- The previous repeats many more times in a non predictable way -->

  <%= f.submit "Submit" %>
<% end %>

因此,如果我不必一次显示所有 bars,这对我来说将是完美的。有人知道怎么做吗?

您可以使用 fields_for 的第二个参数并传递一个范围:

class Bar < ApplicationRecord

  belongs_to :foo

  scope :some_a,->{where(conditions)}
  scope :some_b,->{where(conditions)}

end

在你的表单中

<%= form_for @foo do |f| %>
    <%= f.text_field :foo_attr %>

    <%= f.fields_for :bars, @foo.bars.some_a do |b| %>
        <%= b.hidden_field :other_bar_attr %>
        <%= b.text_field :bar_attr %>
        ...
    <% end %>

    <%= f.fields_for :bars, @foo.bars.some_b do |b| %>
        <%= b.hidden_field :other_bar_attr %>
        <%= b.text_field :bar_attr %>
        ...
    <% end %>
    <%= f.submit %>
<% end %>

您可以使用隐藏输入来设置作用域中使用的默认值。

更新

如果您需要在表单中使用 fields_for 的多个实例,您可以这样做

在控制器中为作用域对象设置一个数组,例如:

class SomeController < AP
  def some_action
    @var_to_the_form = []
    (1..well_know_quantity).each do |value|
      @var_to_the_form << Model.where(conditions)
    end
  end
end

你的表格必须如下

<% @var_to_the_form.each do |records| %>
  <%= f.fields_for :bars, records do |b| %>
    <%= b.hidden_field :other_bar_attr %>
    <%= b.text_field :bar_attr %>
        ...
  <% end %>
<% end %>

重要的部分是了解如何设置传递给视图的记录。

所以,碰巧我只需要 fields_for 每次只显示一个实例。

我发现 fields_for 允许您指定特定对象来呈现字段。所以,我只是创建了一个计数器并每次添加一个 @foo.bars[counter] 并且它神奇地起作用了,它是这样的:

<% counter = 0 %>
<%= form_for @foo do |f| %>

  <!-- foo fields -->

  <%= f.fields_for :bars, @foo.bars[counter] do |f_bar| %>
    <!-- bar fields of one bar -->
  <% end %>
  <% counter+=1 %>

  <!-- other foo fields -->

  <%= f.fields_for :bars, @foo.bars[counter] do |f_bar| %>
    <!-- bar fields of another bar -->
  <% end %>
  <% counter+=1 %>

  <!-- The previous repeats many more times in a non predictable way -->

  <%= f.submit "Submit" %>
<% end %>