Заполнение базы данных Rails предустановленными идентификаторами - PullRequest
2 голосов
/ 05 мая 2010

У меня есть XML-файл, содержащий начальные данные, которые я пытаюсь загрузить в свою производственную базу данных.

Проблема в том, что у меня есть ассоциации между различными типами данных / узлами в файле XML, и поэтому мне нужно, чтобы указанные идентификаторы были одинаковыми при загрузке в MySQL из Rails.

Это прекрасно работает с SQLite во время разработки, я просто использую строку, подобную приведенной ниже, после перебора каждого узла в файле XML:

CardSet.connection.execute("UPDATE card_sets SET id = #{xml_set.attributes['id']} WHERE id = #{set.id}")

Мой вопрос: как я могу принудительно установить предустановленные идентификаторы при заполнении базы данных, а затем снова включить auto_increment, чтобы Rails работал как обычно?

Я попытался сделать это с помощью этих двух строк перед созданием записи в базе данных:

CardSet.connection.execute("ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL")
CardSet.connection.execute("ALTER TABLE card_sets DROP PRIMARY KEY")

и это после:

CardSet.connection.execute("ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL auto_increment PRIMARY KEY")

который MySQL возвращает мне как

Mysql::Error: ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '18' for key 'PRIMARY': ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL auto_increment PRIMARY KEY

Моя схема:

create_table "card_sets", :force => true do |t|
  t.string   "name"
  t.datetime "created_at"
  t.datetime "updated_at"
end

create_table "card_sets_cards", :id => false, :force => true do |t|
  t.integer "card_set_id"
  t.integer "card_id"
end

create_table "cards", :force => true do |t|
  t.text     "question",   :default => ""
  t.text     "answer",     :default => ""
  t.datetime "created_at"
  t.datetime "updated_at"
end

И модели:

class CardSet < ActiveRecord::Base
  has_and_belongs_to_many :cards, :uniq => true
end

class Card < ActiveRecord::Base
    has_and_belongs_to_many :card_set, :uniq => true
end

Любые идеи приветствуются.

Ответы [ 2 ]

5 голосов
/ 30 июля 2010

Мой путь к ошибке MySQL заключался в том, чтобы создать экземпляр модели в обычном режиме (CardSet.create), а затем принудительно обновить идентификатор и затем перезагрузить экземпляр:

c = CardSet.create(...blah....)
CardSet.connection.execute("UPDATE card_sets SET id = #{real_card_set_id} WHERE id = #{c.id}")
c = CardSet.find(real_card_set_id)
c.save!
4 голосов
/ 05 мая 2010

Если вы создадите свои объекты в блочной форме, это сработает.

p = Post.new do |post|
  post.id = 1000
end

p.save
...