Ruby: テーブルの更新または削除が外部キー制約に違反します
概要
現在、Shop.last.destroy を実行するとこのエラーが発生しますが、理由がわかりません。
PG::ForeignKeyViolation: ERROR: update or delete on table "credit_changes" violates foreign key constraint "fk_rails_16918229d0" on table "sms_historicals" (ActiveRecord::InvalidForeignKey)
そしてこれはPostgres DBです
私のモデルは次のようになります。
class SmsHistorical < ApplicationRecord
belongs_to :customer
belongs_to :credit_change, optional: true
belongs_to :notification_setting, optional: true
end
class CreditChange < ActiveRecord::Base
belongs_to :credit
belongs_to :customer
has_one :sms_historicals
has_one :email_historicals
end
これらのテーブルを作成するための移行は次のとおりです。
create_table :credit_changes, if_not_exists: true do |t|
t.integer "credit_id"
t.text "credit_notes"
t.decimal "credit_amount_changed", precision: 4, scale: 2, default: 0.0
t.datetime "date"
t.string "transaction_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
class CreateSmsHistoricals < ActiveRecord::Migration[6.1]
def change
create_table :sms_historicals, if_not_exists: true do |t|
t.string :phone_number
t.text :message
t.references :customer, null: true, foreign_key: true, on_delete: :cascade
t.references :credit_change, null: true, foreign_key: true, on_delete: :cascade
t.references :notification_setting, null: true, foreign_key: true, on_delete: :cascade
t.timestamps
end
end
end
解決策
belongs_to :credit_change は、Sms テーブルと Credit テーブルの間の FK です。そして、クレジット ID は Sms テーブルに保存されます。 Credit を削除する場合は、Sms テーブルのデータもクリアする必要があります。例えば
class CreditChange < ActiveRecord::Base
has_one :sms_historicals, dependent: :nullify
end
Sms テーブルのbelongs_to :credit_changeをオプションとして設定しているため、ここでは :nullify を選択します。ただし、他のものにすることもできます: https://guides.rubyonrails.org/association_basics.html#options-for-has-one