12

私の完全なコードはhttps://github.com/andyw8/simpleform_examplesで見ることができます

ProductCategory次の検証を行う結合モデルがあります。

validates :product, presence: true
validates :category, presence: true

私のProductモデルには次の関連付けがあります。

has_many :product_categories
has_many :categories, through: :product_categories

カテゴリを使用して新しい製品を作成しようとすると@product.save!、コントローラーでの呼び出しが次のように失敗します。

Validation failed: Product categories is invalid

検証を削除すると、すべてが機能し、結合モデルが正しく保存されます。

を使用していますが、この問題に関連する必要strong_parametersはないと思います。

4

3 に答える 3

11

これは、コールバックチェーンの「競合状態」です。

product製品を作成するとき、保存される前にIDがないため、のスコープにはありませんProductCategory

Product.new(name: "modern times", category_ids:[1, 2]) #=> #<Product id: nil >

検証のその段階(保存前)では、ProductCatgory外部キーにIDを割り当てることはできませんproduct_id

これが、関連付けの検証がある理由です。検証がトランザクション全体のスコープで行われるようにするためです。

更新:コメントで述べたように、あなたはまだ製品/カテゴリーの存在を保証することはできません。これを実行する理由に応じて、さまざまな方法があります(たとえば、何らかのフォームを介したProductCategoryへの直接アクセス)

  • あなたが持っているフラグを作成することができますvalidates :product, presence: true, if: :direct_access?
  • または、それらのみを更新できる場合:validates :product, presence: true, on: "update"
  • 最初に(products_controllerで)製品を作成し、後にカテゴリを追加します

...しかし、実際、これらはすべて、単純なものからの妥協または回避策です。@product.create(params)

于 2013-01-09T09:48:03.833 に答える
10

inverse_ofこの問題を解決するために、参加モデルでの指定が文書化されています。

https://github.com/rails/rails/issues/6161#issuecomment-6330795 https://github.com/rails/rails/pull/7661#issuecomment-8614206

簡単な例:

class Product < ActiveRecord::Base
  has_many :product_categories, :inverse_of => :product
  has_many :categories, through: :product_categories
end

class Category < ActiveRecord::Base
  has_many :product_categories, inverse_of: :category
  has_many :products, through: :product_categories
end

class ProductCategory < ActiveRecord::Base
  belongs_to :product
  belongs_to :category

  validates :product, presence: true
  validates :category, presence: true
end

Product.new(:categories => [Category.new]).valid? # complains that the ProductCategory is invalid without inverse_of specified

出典: https://github.com/rails/rails/issues/8269#issuecomment-12032536

于 2015-07-31T16:02:52.463 に答える
0

関係をより適切に定義する必要があることは確かです。まだ見落としがあるかもしれませんが、ご理解いただければ幸いです。

class Product < ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection

  validates :name, presence: true
  validates :description, presence: true
  validates :color_scheme, presence: true

  belongs_to :color_scheme

  has_many :product_categories, inverse_of: :product
  has_many :categories, through: :product_categories
end


class ProductCategory < ActiveRecord::Base
  belongs_to :product
  belongs_to :category

  validates_associated :product
  validates_associated :category

  # TODO work out why this causes ProductsController#create to fail
  # validates :product, presence: true
  # validates :category, presence: true
end


class Category < ActiveRecord::Base
  has_many :product_categories, inverse_of: :category
  has_many :products, through: :product_categories
end
于 2013-01-07T04:24:11.010 に答える