嵌套属性适用于创建,但在更新记录时失败

时间:2014-02-14 14:16:59

标签: ruby-on-rails ruby-on-rails-4

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

主要模型

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相关的模型

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

创建的控制台输出正常工作,看起来像

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)

更新。我不工作,并给出嵌套字段为空的错误。它是更新方法中的pp

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)

1 个答案:

答案 0 :(得分:1)

我想我知道你的代码有什么问题。 accepts_nested_attributes_for不要求您构建任何关联的模型。如果传入适当的参数,则模型会自动构建或更新关联。

update方法的情况下,您所做的是以下内容:

  • 您找到了相关产品。到目前为止一切顺利(尽管您实际上可以在表单中使用特定的产品ID)
  • 然后构建两个产品选项(#set_product)。这就是问题所在。
  • 最后根据参数更新模型。

现在第二步的问题是你基本上构建了两个空的关联实例。这些不受accepts_nested_attributes的影响。因此,您尝试保存2 + 2个产品选项(您构建的产品和由参数创建的产品)。显然,由于两个模型没有设置属性这一事实,您会收到验证错误。

您可以通过从ProductOption中删除验证器来确保我的假设是正确的。在更新时,您应该保留4个关联的产品选项。