Rails автоматически присваивает идентификатор, который уже существует
Я создаю новую запись, например:
truck = Truck.create(:name=>name, :user_id=>2)
В моей базе данных в настоящее время имеется несколько тысяч объектов для грузовика, но я назначил идентификатор нескольким из них, таким образом, чтобы оставить некоторый идентификатор доступным. Итак, что происходит, рельсы создают элемент с id = 150, и он отлично работает. Но затем он пытается создать элемент и назначить его id = 151, но этот идентификатор может уже существовать, поэтому я вижу эту ошибку:
ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "companies_pkey"
DETAIL: Key (id)=(151) already exists.
И в следующий раз, когда я запустим действие, он просто назначит id 152, который будет работать нормально, если это значение еще не принято. Как я могу получить рельсы, чтобы проверить, существует ли идентификатор до его назначения?
Спасибо!
ИЗМЕНИТЬ
Идентификатор Truck - это то, что дублируется. Пользователь уже существует и является константой в этом случае. Фактически это проблема, с которой мне приходится иметь дело. Один из вариантов заключается в том, чтобы воссоздать таблицу, чтобы позволить рельсам автоматически назначать каждый идентификатор на этот раз. Я начинаю думать, что это лучший выбор, потому что у меня есть еще несколько проблем, но миграция для этого будет очень сложной, потому что Truck - это внешний ключ во многих других таблицах. Будет ли простой способ иметь рельсы для создания новой таблицы с теми же данными, которые уже хранятся под грузовиком, с автоматическим назначением идентификатора и поддержанием всех существующих отношений?
Ответы
Ответ 1
Rails, вероятно, использует встроенную последовательность PostgreSQL. Идея последовательности состоит в том, что она используется только один раз.
Простейшим решением является установка последовательности для столбца company.id в наивысшем значении в таблице с таким запросом:
SELECT setval('company_id_seq', (SELECT max(id) FROM company));
Я угадываю ваше имя последовательности "company_id_seq", имя таблицы "компания" и имя столбца "id"..., пожалуйста, замените их на правильные. Вы можете получить имя последовательности с помощью SELECT pg_get_serial_sequence('tablename', 'columname');
или посмотреть определение таблицы с помощью \d tablename
.
Альтернативное решение - переопределить метод save() в вашем классе компании, чтобы вручную установить идентификатор компании для новых строк перед сохранением.
Ответ 2
Я сделал это, чтобы решить эту проблему для меня.
ActiveRecord::Base.connection.tables.each do |t|
ActiveRecord::Base.connection.reset_pk_sequence!(t)
end
Я нашел reset_pk_sequence! из этой темы. http://www.ruby-forum.com/topic/64428
Ответ 3
На основе @Apie answer.
Вы можете выполнить задачу и выполнить ее, когда вам нужно:
rake database:correction_seq_id
Вы создаете такие задачи:
rails g task database correction_seq_id
И в сгенерированном файле (lib/tasks/database.rake
) поместите:
namespace :database do
desc "Correction of sequences id"
task correction_seq_id: :environment do
ActiveRecord::Base.connection.tables.each do |t|
ActiveRecord::Base.connection.reset_pk_sequence!(t)
end
end
end
Ответ 4
Звучит для меня как проблема с базой данных, а не с проблемой Rails. Возможно ли, что ваша база данных имеет неправильное семантическое семя в столбце id
? Чтобы попробовать попробовать сделать пару вставок непосредственно в вашу базу данных и посмотреть, существует ли такое же поведение.
Ответ 5
Я решил эту проблему с помощью следующей команды.
Запустите это в вашей консоли rails
ActiveRecord::Base.connection.reset_pk_sequence!('table_name')