为什么新数据没有以嵌套形式保存?
Why the new data are not saved in the nested form?
在 ActiveAdmin 中,我有一个具有三重嵌套的实体编辑表单。现在我可以编辑数据库中存在的数据。他们得救了。
但是如果我尝试添加新数据,则会收到 ROLLBACK 错误:
{:"blocks.texts.block"=>["must exist", "can't be blank"]}
我会再次澄清 - 此字段中的现有数据已成功更新。
但是在这种嵌套形式中创建新实体时,出现了某种问题。我试图通过日志来跟踪表单中发送的内容、验证之前的内容以及验证之后剩下的内容。
万事俱备:
"blocks_attributes"=>{"0"=>{"texts_attributes"=>{"0"=>{"value"=>"first value", "_destroy"=>"0", "id"=>"671518"}}, "label_ids"=>["", "54"], "_destroy"=>"0", "id"=>"18655"}, "1"=>{"texts_attributes"=>{"0"=>{"value"=>"tteesstt"}}}}
# => "1"=>{"texts_attributes"=>{"0"=>{"value"=>"tteesstt"}}}
但在验证前后,此数据不再可用。在 texts
中仅存在以前存在的数据。
在 ActiveAdmin 中有这个代码:
permit_params :title, :description, :published,
blocks_attributes: [
:id, :_destroy,
texts_attributes: %i[id value _destroy],
label_ids: []
],
category_ids: []
# ...
f.has_many :blocks, allow_destroy: true do |b_f|
b_f.inputs do
b_f.has_many :texts, allow_destroy: true do |b_t_f|
b_t_f.inputs do
b_t_f.input :value
end
end
b_f.input :labels, as: :check_boxes, collection: Label.options_for_select, input_html: { multiple: true }
end
end
最初的Post模型有这个代码:
accepts_nested_attributes_for :blocks,
allow_destroy: true
在块模型中:
accepts_nested_attributes_for :texts,
allow_destroy: true
请问为什么现有的数据更新了,而新的数据一保存就消失了?
加法 1
据我了解,这与 texts
无关,但与 block
- blocks.texts.block
相关。但为什么 text
指的是 block
?为什么 block
无法识别?它的名称格式如下:post[blocks_attributes][1][texts_attributes][0][value]
.
加法2
如果在 ActiveAdmin 中我首先只添加(保存到数据库)block
(第二块),然后在我向这个 block
添加文本之后,所有两次保存到数据库都会成功。即问题是由于单场景创建text
时缺少block
ID
原来这是个bug?添加(使用 JS)新的 HTML 表单代码时,还必须为 text
添加 block_id
。但现在不是了。现在只有数据库中已有的区块才有这个字段。
我记得前段时间我遇到过类似的关联问题。在这里,表单错误看起来文本没有 block_id。这是真的,因为你已经在保存它了。试试看:https://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
解决方法很简单——需要使用inverse_of
。 Documentation.
一切都会按预期开始工作。
在 ActiveAdmin 中,我有一个具有三重嵌套的实体编辑表单。现在我可以编辑数据库中存在的数据。他们得救了。
但是如果我尝试添加新数据,则会收到 ROLLBACK 错误:
{:"blocks.texts.block"=>["must exist", "can't be blank"]}
我会再次澄清 - 此字段中的现有数据已成功更新。
但是在这种嵌套形式中创建新实体时,出现了某种问题。我试图通过日志来跟踪表单中发送的内容、验证之前的内容以及验证之后剩下的内容。
万事俱备:
"blocks_attributes"=>{"0"=>{"texts_attributes"=>{"0"=>{"value"=>"first value", "_destroy"=>"0", "id"=>"671518"}}, "label_ids"=>["", "54"], "_destroy"=>"0", "id"=>"18655"}, "1"=>{"texts_attributes"=>{"0"=>{"value"=>"tteesstt"}}}}
# => "1"=>{"texts_attributes"=>{"0"=>{"value"=>"tteesstt"}}}
但在验证前后,此数据不再可用。在 texts
中仅存在以前存在的数据。
在 ActiveAdmin 中有这个代码:
permit_params :title, :description, :published,
blocks_attributes: [
:id, :_destroy,
texts_attributes: %i[id value _destroy],
label_ids: []
],
category_ids: []
# ...
f.has_many :blocks, allow_destroy: true do |b_f|
b_f.inputs do
b_f.has_many :texts, allow_destroy: true do |b_t_f|
b_t_f.inputs do
b_t_f.input :value
end
end
b_f.input :labels, as: :check_boxes, collection: Label.options_for_select, input_html: { multiple: true }
end
end
最初的Post模型有这个代码:
accepts_nested_attributes_for :blocks,
allow_destroy: true
在块模型中:
accepts_nested_attributes_for :texts,
allow_destroy: true
请问为什么现有的数据更新了,而新的数据一保存就消失了?
加法 1
据我了解,这与 texts
无关,但与 block
- blocks.texts.block
相关。但为什么 text
指的是 block
?为什么 block
无法识别?它的名称格式如下:post[blocks_attributes][1][texts_attributes][0][value]
.
加法2
如果在 ActiveAdmin 中我首先只添加(保存到数据库)block
(第二块),然后在我向这个 block
添加文本之后,所有两次保存到数据库都会成功。即问题是由于单场景创建text
时缺少block
ID
原来这是个bug?添加(使用 JS)新的 HTML 表单代码时,还必须为 text
添加 block_id
。但现在不是了。现在只有数据库中已有的区块才有这个字段。
我记得前段时间我遇到过类似的关联问题。在这里,表单错误看起来文本没有 block_id。这是真的,因为你已经在保存它了。试试看:https://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
解决方法很简单——需要使用inverse_of
。 Documentation.
一切都会按预期开始工作。