使用has_many:through时,连接模型中的验证失败

And*_*ite 10 activerecord ruby-on-rails

我的完整代码可以在https://github.com/andyw8/simpleform_examples上看到

我有一个ProductCategory带有以下验证的连接模型:

validates :product, presence: true
validates :category, presence: true
Run Code Online (Sandbox Code Playgroud)

我的Product模型有以下关联:

has_many :product_categories
has_many :categories, through: :product_categories
Run Code Online (Sandbox Code Playgroud)

当我尝试使用类别创建新产品时,@product.save!控制器中的调用将失败:

Validation failed: Product categories is invalid
Run Code Online (Sandbox Code Playgroud)

当我删除验证时,一切正常,连接模型正确保存.

我正在使用,strong_parameters但我不认为这应该与这个问题有关.

cha*_*sto 11

这是回调链中的"竞争条件".

当您创建产品时,它在保存之前没有任何ID,因此product在范围内没有ProductCategory.

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

在验证阶段(保存之前),ProductCatgory不能将任何id分配给它的外键product_id.

这就是你有关联验证的原因:这样验证就发生在整个事务的范围内

更新:如评论中所述,您仍然无法确保产品/类别的存在.有很多方法取决于你想要这样做的原因(例如通过某种形式直接访问ProductCategory)

  • 你可以创建一个标志 validates :product, presence: true, if: :direct_access?
  • 或者如果你只能更新它们: validates :product, presence: true, on: "update"
  • 首先创建您的产品(在products_controller中)并在之后添加类别

......但事实上,这些都是简单的妥协或变通办法 @product.create(params)


cwe*_*ton 5

指定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
Run Code Online (Sandbox Code Playgroud)

改编自:https : //github.com/rails/rails/issues/8269#issuecomment-12032536