在使用.build创建对象时,Rails会跳过has_many关联的验证

编程语言 2026-07-10

我需要帮忙弄清楚为什么我的验证被忽略了:

我有以下模型...

一个 Headword,可以包含多个 HeadwordDefinition

class Headword < ApplicationRecord
    has_many :definitions, class_name: 'HeadwordDefinition', foreign_key: 'headword_id', dependent: :destroy, inverse_of: 'headword'
    accepts_nested_attributes_for :definitions

    validates_associated :definitions
    # ...
end

以及相应的 HeadwordDefinition

class HeadwordDefinition < ApplicationRecord
  belongs_to :headword, class_name: 'Headword'

  validates :content, uniqueness: true
  validates :order, uniqueness: true

  # ...
end

当我使用 .build 方法按如下方式创建一个 Headword,并建立它的 HeadwordDefinition 关系时:

red = Headword.new(title: 'wouj')

red.definitions.build([{content: 'bugs', order: 1}, {content: 'bugs', order: 1}])

red.save!

对于 HeadwordDefinition 的验证(在本例中是content与 order的唯一性)被完全忽略了!

可以请你帮我找出原因吗?

解决方案

在验证阶段,这两个 HeadwordDefinition 记录都尚未写入数据库。Rails的唯一性验证只检查已持久化的记录,而不会检查一起保存的多个新相关记录之间的重复。

因此验证确实在运行,但它在向数据库提问那些看不到尚未保存的重复同级的情况,Rails实际上是这样处理的:

  1. 验证第一条定义:

  2. 数据表中是否已经存在content = 'bugs' 的行?

  3. 否!

  4. 验证第二条定义:

  5. 数据表中是否已经存在content = 'bugs' 的行?

  6. 否!(因为第一条定义也未保存)

  7. 父对象和子对象被视为有效

  8. Rails将它们保存
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章