samedi 21 septembre 2019

PG::ForeignKeyViolation: ERROR after changing a has_and_belongs_to_many association in rails to a has_many :through association

I recently switched a has_and_belongs_to_many (HABTM) association to a has_many :through association and now I have a lot of failing tests due to violating foreign key constraints. Here's an example test failure message:

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"

Here's the form that creates the association. screenshot of my form

Here are my models with the relevant associations...

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

And the relevant schemas:

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

Everything works fine in the browser. It's just my tests that are failing and all of the failing tests have this same foreign key error.

I don't want to start adding associations and foreign keys to my models just to get my tests passing since the expected behavior is working in the browser.

I'm using fixtures for my tests. Is this the problem? Is there something about my fixtures that could be causing this error? FYI, I want to continue using fixtures and not switch the app to factories.

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

Aucun commentaire:

Enregistrer un commentaire