重要 - 阅读下面的编辑以获取有关问题的更新
当我尝试将新记录添加到 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”也有同样的错误——我在架构上做错了吗?
编辑
系统正在尝试添加相同的项目/技能两次。当我将私有方法更改为此:
def set_starting_skills
skills = profession.starting_skills
end
它不会尝试在连接表中创建任何内容。但是将第一行恢复为 self.skills 如下尝试创建相同的技能 TWICE
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
仅返回一项技能profession.starting_skills
:
1.9.3-p194 :022 > Profession.find(7).starting_skills.each {|x| puts x.id}
54
所以真正的问题变成了:为什么 Rails 会尝试两次添加这个 HABTM 记录?