PG::ForeignKeyViolation:将 rails 中的 has_and_belongs_to_many 关联更改为 has_many 后出错:通过关联
PG::ForeignKeyViolation: ERROR after changing a has_and_belongs_to_many association in rails to a has_many :through association
我最近将 has_and_belongs_to_many
(HABTM) 关联切换为 has_many :through
关联,现在由于违反外键约束,我有很多失败的测试。这是一个示例测试失败消息:
DRb::DRbRemoteError: PG::ForeignKeyViolation: ERROR: update or delete on table "choices" violates foreign key constraint "fk_rails_d6ffbc38aa" on table "selections"
DETAIL: Key (id)=(506907318) is still referenced from table "selections"
这是创建关联的表单。
这是我与相关协会的模型...
models/variant.rb
class Variant < ApplicationRecord
has_many :selections
has_many :choices, through: :selections
end
models/choice.rb
class Choice < ApplicationRecord
has_many :variants, through: :selections
belongs_to :option
end
models/selection.rb
class Selection < ApplicationRecord
belongs_to :choice
belongs_to :variant
end
以及相关架构:
create_table "variants", force: :cascade do |t|
t.string "sku"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "account_id"
t.bigint "product_id"
t.index ["account_id"], name: "index_variants_on_account_id"
t.index ["product_id"], name: "index_variants_on_product_id"
end
create_table "choices", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "option_id"
t.bigint "account_id"
t.index ["account_id"], name: "index_choices_on_account_id"
t.index ["option_id"], name: "index_choices_on_option_id"
end
create_table "selections", force: :cascade do |t|
t.bigint "choice_id"
t.bigint "variant_id"
t.datetime "created_at", precision: 6
t.datetime "updated_at", precision: 6
t.index ["choice_id"], name: "index_selections_on_choice_id"
t.index ["variant_id"], name: "index_selections_on_variant_id"
end
在浏览器中一切正常。只是我的测试失败了,所有失败的测试都有同样的外键错误。
我不想开始向我的模型添加关联和外键只是为了让我的测试通过,因为预期的行为在浏览器中有效。
我正在使用固定装置进行测试。这是问题吗?我的灯具是否有什么可能导致此错误?仅供参考,我想继续使用固定装置而不是将应用程序切换到工厂。
test/fixtures/variants.yml
small_t_shirt_in_red:
id: 1
account: fuzz
product: t_shirt
sku: FUZZ-T-001
choices: small, red
medium_generic_gadget_in_blue:
id: 2
account: generic_gadgets
product: gadget
sku: GENERIC-001
choices: medium, blue
test/fixtures/choices.yml
small:
name: Small
medium:
name: Medium
large:
name: Large
red:
name: Red
blue:
name: Blue
test/fixtures/selections.yml
small_t_shirt_selection:
choice_id: 1
variant_id: 1
red_t_shirt_selection:
choice_id: 4
variant_id: 1
medium_generic_selection:
choice_id: 2
variant_id: 2
blue_generic_selection:
choice_id: 5
variant_id: 2
尝试删除并重新创建您的测试数据库:
RAILS_ENV=test rails db:drop db:create
也许测试数据库中有外键约束,而 main/dev 数据库没有。
更新
我发现了这个问题,所以在这里发布解决方案以防其他人需要它。
以下是有效的装置:
test/fixtures/variants.yml
small_t_shirt_in_red:
account: fuzz
product: t_shirt
sku: FUZZ-T-001
choices: small, red
medium_generic_gadget_in_blue:
account: generic_gadgets
product: gadget
sku: GENERIC-001
choices: medium, blue
test/fixtures/choices.yml
small:
name: Small
medium:
name: Medium
large:
name: Large
red:
name: Red
blue:
name: Blue
test/fixtures/selections.yml
red_t_shirt_selection:
choice: red
variant: small_t_shirt_in_red
medium_generic_selection:
choice: medium
variant: medium_generic_gadget_in_blue
然后,我需要将我的模型更新为:
models/variant.rb
class Variant < ApplicationRecord
has_many :selections, dependent: :destroy
has_many :choices, through: :selections
end
models/choice.rb
class Choice < ApplicationRecord
has_many :selections, dependent: :destroy
has_many :variants, through: :selections
belongs_to :option
end
models/selection.rb
class Selection < ApplicationRecord
belongs_to :choice
belongs_to :variant
end
我在 Variant
和 Choice
型号上都缺少 has_many :selections, dependent: :destroy
。
我最近将 has_and_belongs_to_many
(HABTM) 关联切换为 has_many :through
关联,现在由于违反外键约束,我有很多失败的测试。这是一个示例测试失败消息:
DRb::DRbRemoteError: PG::ForeignKeyViolation: ERROR: update or delete on table "choices" violates foreign key constraint "fk_rails_d6ffbc38aa" on table "selections"
DETAIL: Key (id)=(506907318) is still referenced from table "selections"
这是创建关联的表单。
这是我与相关协会的模型...
models/variant.rb
class Variant < ApplicationRecord
has_many :selections
has_many :choices, through: :selections
end
models/choice.rb
class Choice < ApplicationRecord
has_many :variants, through: :selections
belongs_to :option
end
models/selection.rb
class Selection < ApplicationRecord
belongs_to :choice
belongs_to :variant
end
以及相关架构:
create_table "variants", force: :cascade do |t|
t.string "sku"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "account_id"
t.bigint "product_id"
t.index ["account_id"], name: "index_variants_on_account_id"
t.index ["product_id"], name: "index_variants_on_product_id"
end
create_table "choices", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "option_id"
t.bigint "account_id"
t.index ["account_id"], name: "index_choices_on_account_id"
t.index ["option_id"], name: "index_choices_on_option_id"
end
create_table "selections", force: :cascade do |t|
t.bigint "choice_id"
t.bigint "variant_id"
t.datetime "created_at", precision: 6
t.datetime "updated_at", precision: 6
t.index ["choice_id"], name: "index_selections_on_choice_id"
t.index ["variant_id"], name: "index_selections_on_variant_id"
end
在浏览器中一切正常。只是我的测试失败了,所有失败的测试都有同样的外键错误。
我不想开始向我的模型添加关联和外键只是为了让我的测试通过,因为预期的行为在浏览器中有效。
我正在使用固定装置进行测试。这是问题吗?我的灯具是否有什么可能导致此错误?仅供参考,我想继续使用固定装置而不是将应用程序切换到工厂。
test/fixtures/variants.yml
small_t_shirt_in_red:
id: 1
account: fuzz
product: t_shirt
sku: FUZZ-T-001
choices: small, red
medium_generic_gadget_in_blue:
id: 2
account: generic_gadgets
product: gadget
sku: GENERIC-001
choices: medium, blue
test/fixtures/choices.yml
small:
name: Small
medium:
name: Medium
large:
name: Large
red:
name: Red
blue:
name: Blue
test/fixtures/selections.yml
small_t_shirt_selection:
choice_id: 1
variant_id: 1
red_t_shirt_selection:
choice_id: 4
variant_id: 1
medium_generic_selection:
choice_id: 2
variant_id: 2
blue_generic_selection:
choice_id: 5
variant_id: 2
尝试删除并重新创建您的测试数据库:
RAILS_ENV=test rails db:drop db:create
也许测试数据库中有外键约束,而 main/dev 数据库没有。
更新
我发现了这个问题,所以在这里发布解决方案以防其他人需要它。
以下是有效的装置:
test/fixtures/variants.yml
small_t_shirt_in_red:
account: fuzz
product: t_shirt
sku: FUZZ-T-001
choices: small, red
medium_generic_gadget_in_blue:
account: generic_gadgets
product: gadget
sku: GENERIC-001
choices: medium, blue
test/fixtures/choices.yml
small:
name: Small
medium:
name: Medium
large:
name: Large
red:
name: Red
blue:
name: Blue
test/fixtures/selections.yml
red_t_shirt_selection:
choice: red
variant: small_t_shirt_in_red
medium_generic_selection:
choice: medium
variant: medium_generic_gadget_in_blue
然后,我需要将我的模型更新为:
models/variant.rb
class Variant < ApplicationRecord
has_many :selections, dependent: :destroy
has_many :choices, through: :selections
end
models/choice.rb
class Choice < ApplicationRecord
has_many :selections, dependent: :destroy
has_many :variants, through: :selections
belongs_to :option
end
models/selection.rb
class Selection < ApplicationRecord
belongs_to :choice
belongs_to :variant
end
我在 Variant
和 Choice
型号上都缺少 has_many :selections, dependent: :destroy
。