嵌套属性适用于创建但在更新记录时失败 [英] nested attributes works for create but fails when update a record
问题描述
我有嵌套属性的问题.创建工作但当我更新时,错误消息显示未设置关系中的值.我找不到原因.
I have a problem with nested attributes. Creating works but when I update, the error message shows me that the values in the relation are not set. I can't find the reason.
主要型号
class Product < ActiveRecord::Base
has_many :product_options
accepts_nested_attributes_for :product_options,
:allow_destroy => true,
:reject_if => proc { | r | r["name"].blank? or r["value"].blank? }
end
嵌套模型
class ProductOption < ActiveRecord::Base
belongs_to :product
validates :name, :presence => true
validates :value, :presence => true
end
控制器有点短路.Items 是一个模型,其中 Product 与 has_one 相关
The controller is a bit shorted. Items is a model where Product is related to as has_one
class Admin::ProductsController < Admin::ApplicationController
before_action :set_product, only: [ :new, :show, :edit, :update, :destroy ]
def create
@product = Product.new( product_params )
respond_to do |format|
if @product.save
@product.product_options.build
format.js { render :js => "alert( 'Daten gespeichert!' );" }
else
format.js { render :js => 'alert( "Fehler beim Speichern!" );' }
end
end
end
def update
respond_to do |format|
if @product.update( product_params )
format.js { render :js => "alert( 'Daten gespeichert!' );" }
else
require "pp"
pp @product.errors
format.js { render :js => 'alert( "Fehler beim Speichern!" );' }
end
end
end
private
# UPDATE: creating the product_options at this time
# produces the described error :)
def set_product
@item = Item.find_by_id( params[ :item_id ] ) if params[ :item_id ]
@product = @item.product ? @item.product : @item.build_product
# WRONG Place for generating new options
# 2.times { @product.product_options.build }
end
def product_params
params.require( :product ).permit( :item_id, :name, :title, :active, :product_options_attributes => [ :id, :name, :value, :_destroy ] )
end
end
创建的控制台输出正在工作,看起来像
The console output for the create is working and looks like
Started POST "/admin/items/653/product" for 127.0.0.1 at 2014-02-14 15:12:14 +0100
Processing by Admin::ProductsController#create as JS
Parameters: {"utf8"=>"✓", "product"=>{"item_id"=>"653", "name"=>"1", "title"=>"1", "active"=>"1", "product_options_attributes"=>{"0"=>{"name"=>"aaa", "value"=>"aaaa"}}}, "commit"=>"Create Product", "item_id"=>"653"}
User Load (1.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 6 ORDER BY "users"."id" ASC LIMIT 1
(0.6ms) BEGIN
SQL (17.5ms) INSERT INTO "products" ("created_at", "item_id", "name", "title", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Fri, 14 Feb 2014 14:12:14 UTC +00:00], ["item_id", 653], ["name", "1"], ["title", "1"], ["updated_at", Fri, 14 Feb 2014 14:12:14 UTC +00:00]]
SQL (1.3ms) INSERT INTO "product_options" ("created_at", "name", "product_id", "updated_at", "value") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Fri, 14 Feb 2014 14:12:14 UTC +00:00], ["name", "aaa"], ["product_id", 28], ["updated_at", Fri, 14 Feb 2014 14:12:14 UTC +00:00], ["value", "aaaa"]]
Item Load (1.0ms) SELECT "items".* FROM "items" WHERE "items"."id" = $1 ORDER BY "items"."id" ASC LIMIT 1 [["id", 653]]
ProductOption Load (1.3ms) SELECT "product_options".* FROM "product_options" WHERE "product_options"."product_id" = $1 [["product_id", 28]]
Rendered admin/products/_show.html.erb (7.6ms)
Rendered admin/products/create.js.erb (9.2ms)
Completed 200 OK in 448ms (Views: 40.0ms | ActiveRecord: 27.1ms)
更新.我不工作并给出嵌套字段为空的错误.就是update方法里面的pp
The the update. I doesn't work and gives an error that the nested fields are empty. It's the pp inside the update method
Started PATCH "/admin/items/653/product" for 127.0.0.1 at 2014-02-14 15:15:03 +0100
Processing by Admin::ProductsController#update as JS
Parameters: {"utf8"=>"✓", "product"=>{"item_id"=>"653", "name"=>"1", "title"=>"1", "active"=>"1", "product_options_attributes"=>{"0"=>{"name"=>"aaa", "value"=>"aaaa", "id"=>"9"}, "1"=>{"name"=>"bbb", "value"=>"bbbb"}}}, "commit"=>"Update Product", "item_id"=>"653"}
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 6 ORDER BY "users"."id" ASC LIMIT 1
Item Load (0.6ms) SELECT "items".* FROM "items" WHERE "items"."id" = 653 LIMIT 1
Product Load (0.9ms) SELECT "products".* FROM "products" WHERE "products"."item_id" = $1 ORDER BY "products"."id" ASC LIMIT 1 [["item_id", 653]]
(0.6ms) BEGIN
ProductOption Load (1.3ms) SELECT "product_options".* FROM "product_options" WHERE "product_options"."product_id" = $1 AND "product_options"."id" IN (9) [["product_id", 28]]
(0.5ms) ROLLBACK
#<ActiveModel::Errors:0x007f8bdeb9f818
@base=
#<Product id: 28, item_id: 653, content: nil, active: 1, created_at: "2014-02-14 14:12:14", updated_at: "2014-02-14 14:12:14", name: "1", title: "1", ordernumber: "">,
@messages=
{:"product_options.name"=>["can't be blank"],
:"product_options.value"=>["can't be blank"]}>
Completed 200 OK in 18ms (Views: 0.1ms | ActiveRecord: 5.1ms)
推荐答案
我想我知道你的代码有什么问题.accepts_nested_attributes_for
不需要您构建任何关联的模型.如果传入适当的参数,则模型会自动构建或更新关联.
I think I know what is the problem with your code. The accepts_nested_attributes_for
does not require you to build any of the associated models. If the appropriate params are passed in then the model automatically builds or updates the associations.
在您的 update
方法中,您执行的操作如下:
In your case in the update
method what you do is the following:
- 您找到相关产品.到目前为止一切顺利(尽管您实际上可以在表单中使用特定的产品 ID)
- 然后构建两个产品选项(在
#set_product
中).这就是问题所在. - 最后,您根据参数更新模型.
- You find the relevant product. So far so good (although you could actually use a specific product id in your form)
- Then you build two product options (in
#set_product
). This is the problem. - And in the end you update the model based on the parameters.
现在第二步的问题是你基本上构建了两个空的关联实例.这些不受accepts_nested_attributes
的影响.因此,您正在尝试保存 2+2 个产品选项(您构建的选项和由参数创建的选项).显然,由于这两个模型没有设置属性,您会得到验证错误.
Now the problem with the second step is that you basically build two empty associated instances. Those are not affected by the accepts_nested_attributes
. As a result you are trying to save 2+2 product options (the ones you build and the ones created by the params). Obviously you get the validation error due to the fact the two of the models have no attributes set.
您可以通过从 ProductOption 中删除验证器来确保我的假设是正确的.更新时,您应该会保留 4 个关联的产品选项.
You can make sure my hypothesis is correct by removing the validators from ProductOption. On update you should get 4 associated product options persisted.
这篇关于嵌套属性适用于创建但在更新记录时失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!