重要-問題の更新については、以下の編集をお読みください
SQLite3で一意の複合キーインデックスを使用して結合テーブルに新しいレコードを追加しようとすると、偽のエラーだと思うものが表示されます。私が行ったすべての(手動)テストでは、データベースはdb:dropに続いてdb:migrateを使用して完全に再構築されていることに注意してください。
エラー:
ActiveRecord::RecordNotUnique
SQLite3::ConstraintException: columns adventurer_id, item_id are not unique:
INSERT INTO "adventurers_items" ("adventurer_id", "item_id") VALUES (1, 68)
エラーを生成するコード:
class Adventurer < ActiveRecord::Base
after_create :set_starting_skills
after_create :set_starting_items
has_and_belongs_to_many :items
has_and_belongs_to_many :skills
# automatically add starting skills on creation
def set_starting_skills
self.skills = self.profession.starting_skills
end
# automatically add starting items on creation
def set_starting_items
self.items = self.profession.items
end
結合テーブルadventurers_skillsを作成する移行:
class AdventurersItems < ActiveRecord::Migration
def change
create_table :adventurers_items do |t|
t.integer :item_id, :null => false
t.integer :adventurer_id, :null => false
end
add_index :adventurers_items, :item_id
add_index :adventurers_items, :adventurer_id
add_index :adventurers_items, [:adventurer_id, :item_id], :unique => true
テーブルは存在し、完全に空です。一意性の制約のために、アプリケーションがこのレコードを挿入できないのはなぜですか?同等のテーブル「adventurers_skills」でも同じエラーが発生します。アーキテクチャ的に何か間違ったことをしていますか?
編集
システムは同じアイテム/スキルを2回追加しようとしています。プライベートメソッドをこれに変更すると:
def set_starting_skills
skills = profession.starting_skills
end
結合テーブルに何も作成しようとはしません。ただし、以下のように最初の行をself.skillsに戻すと、同じスキルが2回作成されます。
def set_starting_skills
self.skills = profession.starting_skills
end
戻り値
(0.4ms) INSERT INTO "adventurers_skills" ("adventurer_id", "skill_id") VALUES (4, 54)
(4.9ms) INSERT INTO "adventurers_skills" ("adventurer_id", "skill_id") VALUES (4, 54)
SQLite3::ConstraintException: columns adventurer_id, skill_id are not unique:
INSERT INTO "adventurers_skills" ("adventurer_id", "skill_id") VALUES (4, 54)
(3.2ms) rollback transaction
返されるスキルは1つだけですprofession.starting_skills
:
1.9.3-p194 :022 > Profession.find(7).starting_skills.each {|x| puts x.id}
54
したがって、本当の問題は次のようになりました。RailsがこのHABTMレコードを2回追加しようとしているのはなぜですか。