嵌套属性适用于创建但在更新记录时失败 [英] nested attributes works for create but fails when update a record

查看:60
本文介绍了嵌套属性适用于创建但在更新记录时失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有嵌套属性的问题.创建工作但当我更新时,错误消息显示未设置关系中的值.我找不到原因.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆