双嵌套关联 w/Cocoon 和多态性被拒绝
Double nested association w/ Cocoon and Polymorphism gets rejected
所以,我有一个模型 Label
是多态的,另一个模型 Stuff
不是。一个 stuff 可以有很多 labels (也可以称为组),并且 each 和它们中的每一个也可以有一个标签。我正在使用 Cocoon gem 尝试将这些资源添加到单个 edit/new 表单(Stuff
表单)。问题是当我尝试用一个新组(其中有新标签)更新 stuff 时,它说这个 Labels labels labelable must exist
。我认为这是一个错误,因为第一个标签(组)还没有保存到数据库中,所以它不能给他的嵌套标签一个 id。 (虽然不确定)
此外,这是最好的方法吗?我的意思是,我将标签设为多态只是因为我只需要保存一个字符串,这是不切实际的,而且它会白白占用数据库存储...
废话少说,这是我的代码:
<div class="form-group">
<label>Groups:</label>
<div id="group" class="col-md-12 p-0 pl-md-3">
<%= form.fields_for :labels do |groupForm| %>
<%= render 'group_fields', f: groupForm %>
<% end %>
<div class="text-center">
<%= link_to_add_association 'Add Group', form, :labels, partial: 'group_fields', class: 'btn btn-success',
wrap_object: Proc.new { |group| group.labels.build; group } %>
</div>
</div>
</div>
我的 _form.html.erb
<div class="nested-fields">
<div class="field form-group row">
<%= f.label :name, class: 'col-sm-1 col-form-label' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control ml-2' %>
</div>
<div class="col-sm-1 p-0">
<%= link_to_remove_association "×".html_safe, f, class: 'badge badge-pill badge-danger mt-2' %>
</div>
<div class="col-12">
<div id="label" class="col-md-12 p-0 pl-md-5 pt-2">
<%= f.fields_for :labels do |labelForm| %>
<%= render 'label_fields', f: labelForm %>
<% end %>
<div class="text-center">
<%= link_to_add_association 'Add Label', f, :labels, class: 'btn btn-success' %>
</div>
</div>
</div>
</div>
</div>
那是在 _group_fields.html.erb
<div class="nested-fields">
<div class="field form-group row mb-2">
<%= f.label :name, class: 'col-sm-1 col-form-label' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control ml-2' %>
</div>
<div class="col-sm-1 p-0">
<%= link_to_remove_association "×".html_safe, f, class: 'badge badge-pill badge-danger mt-2' %>
</div>
</div>
</div>
这是我的 _label_fields.html.erb
class Label < ApplicationRecord
belongs_to :labelable, polymorphic: true
has_many :labels, as: :labelable, dependent: :destroy
accepts_nested_attributes_for :labels, allow_destroy: true, reject_if: proc { |att| att[:name].blank? }
end
这是我的标签模型
class Stuff< ApplicationRecord
has_many :labels, as: :labelable, dependent: :destroy
accepts_nested_attributes_for :labels, allow_destroy: true, reject_if: proc { |att| att[:name].blank? }
end
这是我的 Stuff 模型
我忘了说,如果我只添加标签(组)的第一个 "layer" 而没有在标签上写任何东西(第二个 "layer")并提交表格(我可以这样做它也会更新数据库)当我回来编辑时,我实际上可以毫无问题地修改第二个"layer"。
belongs_to
关系默认为 "required"。这意味着它必须在保存时填写。但是,当保存一个带有嵌套子项的项目时,还不知道 id,而且很明显,rails 无法知道将它们保存在一起时将设置 belongs-to
关联。
有两种处理方法:
- 使
belongs_to
可选,这将跳过验证,并且保存将起作用。像 belongs_to :labelable, polymorphic: true, optional: true
- 更好,声明
inverse_of
,这样rails在保存labels
时就知道它对应于labelable
关系。
像这样:
has_many :labels, as: :labelable, dependent: :destroy, inverse_of: :labelable
您可以在任何关联上声明 inverse_of
,在 belongs_to
上也是如此,但在大多数情况下,只需在 has_many
上声明它就足够了。在您的特定情况下可能还不够。
所以,我有一个模型 Label
是多态的,另一个模型 Stuff
不是。一个 stuff 可以有很多 labels (也可以称为组),并且 each 和它们中的每一个也可以有一个标签。我正在使用 Cocoon gem 尝试将这些资源添加到单个 edit/new 表单(Stuff
表单)。问题是当我尝试用一个新组(其中有新标签)更新 stuff 时,它说这个 Labels labels labelable must exist
。我认为这是一个错误,因为第一个标签(组)还没有保存到数据库中,所以它不能给他的嵌套标签一个 id。 (虽然不确定)
此外,这是最好的方法吗?我的意思是,我将标签设为多态只是因为我只需要保存一个字符串,这是不切实际的,而且它会白白占用数据库存储...
废话少说,这是我的代码:
<div class="form-group">
<label>Groups:</label>
<div id="group" class="col-md-12 p-0 pl-md-3">
<%= form.fields_for :labels do |groupForm| %>
<%= render 'group_fields', f: groupForm %>
<% end %>
<div class="text-center">
<%= link_to_add_association 'Add Group', form, :labels, partial: 'group_fields', class: 'btn btn-success',
wrap_object: Proc.new { |group| group.labels.build; group } %>
</div>
</div>
</div>
我的 _form.html.erb
<div class="nested-fields">
<div class="field form-group row">
<%= f.label :name, class: 'col-sm-1 col-form-label' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control ml-2' %>
</div>
<div class="col-sm-1 p-0">
<%= link_to_remove_association "×".html_safe, f, class: 'badge badge-pill badge-danger mt-2' %>
</div>
<div class="col-12">
<div id="label" class="col-md-12 p-0 pl-md-5 pt-2">
<%= f.fields_for :labels do |labelForm| %>
<%= render 'label_fields', f: labelForm %>
<% end %>
<div class="text-center">
<%= link_to_add_association 'Add Label', f, :labels, class: 'btn btn-success' %>
</div>
</div>
</div>
</div>
</div>
那是在 _group_fields.html.erb
<div class="nested-fields">
<div class="field form-group row mb-2">
<%= f.label :name, class: 'col-sm-1 col-form-label' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control ml-2' %>
</div>
<div class="col-sm-1 p-0">
<%= link_to_remove_association "×".html_safe, f, class: 'badge badge-pill badge-danger mt-2' %>
</div>
</div>
</div>
这是我的 _label_fields.html.erb
class Label < ApplicationRecord
belongs_to :labelable, polymorphic: true
has_many :labels, as: :labelable, dependent: :destroy
accepts_nested_attributes_for :labels, allow_destroy: true, reject_if: proc { |att| att[:name].blank? }
end
这是我的标签模型
class Stuff< ApplicationRecord
has_many :labels, as: :labelable, dependent: :destroy
accepts_nested_attributes_for :labels, allow_destroy: true, reject_if: proc { |att| att[:name].blank? }
end
这是我的 Stuff 模型
我忘了说,如果我只添加标签(组)的第一个 "layer" 而没有在标签上写任何东西(第二个 "layer")并提交表格(我可以这样做它也会更新数据库)当我回来编辑时,我实际上可以毫无问题地修改第二个"layer"。
belongs_to
关系默认为 "required"。这意味着它必须在保存时填写。但是,当保存一个带有嵌套子项的项目时,还不知道 id,而且很明显,rails 无法知道将它们保存在一起时将设置 belongs-to
关联。
有两种处理方法:
- 使
belongs_to
可选,这将跳过验证,并且保存将起作用。像belongs_to :labelable, polymorphic: true, optional: true
- 更好,声明
inverse_of
,这样rails在保存labels
时就知道它对应于labelable
关系。
像这样:
has_many :labels, as: :labelable, dependent: :destroy, inverse_of: :labelable
您可以在任何关联上声明 inverse_of
,在 belongs_to
上也是如此,但在大多数情况下,只需在 has_many
上声明它就足够了。在您的特定情况下可能还不够。