Подтвердить что ты не робот

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 - это внешний ключ во многих других таблицах. Будет ли простой способ иметь рельсы для создания новой таблицы с теми же данными, которые уже хранятся под грузовиком, с автоматическим назначением идентификатора и поддержанием всех существующих отношений?

4b9b3361

Ответ 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')