2013-02-18 3 views
0

Я использую задачу rake для заполнения моей базы данных некоторыми исходными данными. Я хочу создать кучу записей в таблице с помощью первых нескольких идентификаторов, поэтому они всегда присутствуют и всегда имеют эти идентификаторы. Я не против, если в среде dev кто-то добавляет/удаляет/изменяет записи, но я всегда хочу, чтобы первые 5 идентификаторов имели значения. Вот упрощенная версия моего файла Lib/задач/bootstrap.rb:Создание сбоя, когда идентификатор уже существует

namespace :bootstrap do 
    desc "Create the default problem types" 
    task :default_problem_types => :environment do 
     ProblemType.create(:id => 1, :name => 'Wrong location', :description => 'blah') 
     ProblemType.create(:id => 2, :name => 'Wrong name', :description => 'blah') 
     ProblemType.create(:id => 3, :name => 'Wrong details', :description => 'blah') 
     ProblemType.create(:id => 4, :name => 'Duplicate', :description => 'blah') 
     ProblemType.create(:id => 5, :name => 'No longer exists', :description => 'blah') 
    end 

    desc "Run all bootstrapping tasks" 
    task :all => [:default_problem_types] 
end 

Это отлично работает на пустой базе данных. Это создает 5 новых записей в таблице problem_types:

1 - Wrong Location 
2 - Wrong name 
3 - Wrong details 
4 - Duplicate 
5 - No longer exists 

Проблема заключается в том, что если я запускаю его во второй раз, он создает 5 новых записей, с идентификаторами 6, 7, 8, 9, 10. Это несмотря на то, факт, что я предоставил идентификаторы вызова create(), которые уже существуют. Я ожидаю, что эти призывы потерпеть неудачу, потому что если я пытаюсь сделать следующий SQL:

insert into problem_types (id, name, description) values (1, 'foo', 'bar'); 

... он не:

ERROR 1062 (23000): Дублирование записи '1' для ключа ' PRIMARY '

Как получить метод create() для отказа, если идентификатор уже существует?

Спасибо.

+1

Почему вы используете рейк-задачу вместо семян? С семенами, если вы правильно очищаете свою БД, у вас всегда могут быть идентификаторы 1-5 –

+0

Я использовал рейк-задачу, потому что я столкнулся с другим сообщением, рекомендующим это, и я не был знаком с семенами. Однако, прочитав свой комментарий, я посмотрел семена и подумал, что семена более уместны. – antun

+0

Я перехожу к семенам, но когда я делаю ProblemType.delete_all, то заново их создайте (используя ProblemType.find_or_initialize_by_name()) идентификаторы не начинаются с 1-5; они продолжают увеличиваться. (Я использую mySQL локально). Есть ли другой способ правильно очистить БД? – antun

ответ

0

использовать динамический find_or_create_by или find_or_initialize_by метод. Вы можете узнать больше об этом в Rails guides for the Active Record query interface. Они позволяют вам написать что-то вроде этого для каждого ProblemType без создания дубликатов по имени:

problem_type = ProblemType.find_or_initialize_by_name('Wrong location') 
problem_type.description = "blah" 
problem_type.save 

Я согласен с @benchwarmer; лучше избегать управления первичным ключом самостоятельно. Если у вас есть числовой идентификатор, который имеет некоторое семантическое значение, попробуйте добавить отдельный столбец и соответствующим образом установить это значение.

+0

Метод find_or_initialize_by_name работал для меня. Благодаря! – antun

0

Правило большого пальца: вы не присваиваете идентификатор самостоятельно. Пусть база данных выполняет свою работу. Если вы хотите, чтобы ваши имена проблемы быть уникальными, то вы можете добавить validates_uniqueness_of :name в файл модели и запись не будет созданы, если же имя существует

+0

Да, я не был так обеспокоен тем, что идентификаторы были 1-5, поскольку у меня не было дубликатов. Предложение @ rossta об использовании имени (find_or_initialize_by_name) сделало трюк. – antun

Смежные вопросы