2

重要-問題の更新については、以下の編集をお読みください

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回追加しようとしているのはなぜですか。

4

1 に答える 1

0

関係宣言 ( ) のafter_create :set_starting_skillsにコールバック宣言 ( )を入れる必要があります。has_and_belongs_to_many :skills

つまり、モデル内の行の順序は重要です。そうしないと、このバグが発生します。

これは狂気であり、それにはGitHub の問題があります。

于 2013-07-19T20:54:25.427 に答える