Rails auto-assigning id yang sudah ada

93

Saya membuat rekor baru seperti ini:

truck = Truck.create(:name=>name, :user_id=>2)

Database saya saat ini memiliki beberapa ribu entitas untuk truk, tetapi saya menetapkan id ke beberapa di antaranya, dengan cara yang membuat beberapa id tersedia. Jadi yang terjadi adalah rel membuat item dengan id = 150 dan berfungsi dengan baik. Tetapi kemudian mencoba untuk membuat item dan menetapkannya id = 151, tetapi id itu mungkin sudah ada, jadi saya melihat kesalahan ini:

ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "companies_pkey" DETAIL: Key (id)=(151) already exists.

Dan lain kali saya menjalankan tindakan, itu hanya akan menetapkan id 152, yang akan berfungsi dengan baik jika nilai itu belum diambil. Bagaimana saya bisa mendapatkan rel untuk memeriksa apakah ID sudah ada sebelum menetapkannya?

Terima kasih!

EDIT

Id truk adalah apa yang sedang diduplikasi. Pengguna sudah ada dan dalam kasus ini adalah konstanta. Ini sebenarnya adalah masalah warisan yang harus saya tangani. Salah satu opsinya, adalah membuat ulang tabel di let rails secara otomatis menetapkan setiap id kali ini. Saya mulai berpikir ini mungkin pilihan terbaik karena saya memiliki beberapa masalah lain, tetapi migrasi untuk melakukan ini akan sangat rumit karena Truck adalah kunci asing di banyak tabel lainnya. Akankah ada cara sederhana untuk membuat rel membuat tabel baru dengan data yang sama sudah disimpan di bawah Truck, dengan ID yang ditetapkan secara otomatis dan mempertahankan semua hubungan yang ada?

A-bagus
sumber
mengapa Anda tidak membiarkan rel menetapkan ID secara otomatis? Itu akan menghilangkan bahaya duplikasi - atau apakah ini masalah data lama di mana Anda harus menyimpan ID lama? Hanya ingin memahami sedikit kasus bisnis karena ini bukan bisnis seperti biasa saat membuat objek baru.
MBHNYC
@MBHNYC Saya pikir D-Nice menugaskan user_id saat membuat perusahaan, dan bukan id seperti yang Anda pikirkan (dan saya lakukan sebentar juga).
Anil
Ooo, tangkap bagus Anil - Anda benar sekali. @ D-Bagus, mungkin menambahkan migrasi Anda untuk tabel ini ke posting Anda jika ada yang aneh? Anda tergoda untuk mengedit user_id tersebut untuk menghilangkan kebingungan ..
MBHNYC
Tidak, maaf tidak jelas, ID Perusahaan yang diduplikasi. Pengguna sudah ada dan dalam kasus ini adalah konstanta. Ini sebenarnya adalah masalah warisan yang harus saya tangani. Akan mengedit posting dengan info lebih lanjut
D-Nice
Anda tidak perlu membuat ulang tabel. Lihat saja jawaban saya untuk mengatur ulang urutan.
Dondi Michael Stroma

Jawaban:

87

Rails mungkin menggunakan urutan PostgreSQL bawaan. Ide urutan adalah bahwa itu hanya digunakan sekali.

Solusi paling sederhana adalah dengan mengatur urutan kolom company.id Anda ke nilai tertinggi dalam tabel dengan query seperti ini:

SELECT setval('company_id_seq', (SELECT max(id) FROM company));

Saya menebak nama urutan Anda "company_id_seq", nama tabel "perusahaan", dan nama kolom "id" ... tolong ganti dengan yang benar. Anda bisa mendapatkan nama urutan dengan SELECT pg_get_serial_sequence('tablename', 'columname');atau melihat definisi tabel dengan \d tablename.

Solusi alternatifnya adalah menimpa metode save () di kelas perusahaan Anda untuk secara manual mengatur id perusahaan untuk baris baru sebelum menyimpan.

Dondi Michael Stroma
sumber
Saya menebak apa yang akan dilakukan adalah mulai penetapan otomatis dengan apa yang saat ini merupakan nilai tertinggi + 1?
D-Nice
Saya pikir ini adalah jawaban terbaik untuk pertanyaan saya, namun, untuk alasan yang tidak terkait, saya harus menemukan cara untuk menggunakan strategi yang saya jelaskan dalam pengeditan OP saya
D-Nice
Saya tidak mengerti mengapa ini terjadi pada awalnya? Ini telah terjadi pada saya dan saya ingin memahami bagaimana ini mungkin.
Berburu Burdick
2
@Websitescenes, jika seseorang memiliki kolom SERIAL di PostgreSQL (kolom serial adalah kolom di mana nilai defaultnya adalah nilai berikutnya secara berurutan), lalu mengisi tabel dengan nilai keras di kolom tersebut, urutan tersebut tidak akan diperbarui secara otomatis. Contoh: create table t (id serial not null primary key); insert into t values (1); insert into t values (default); ERROR: duplicate key value violates unique constraint "t_pkey" DETAIL: Key (id)=(1) already exists.
Dondi Michael Stroma
207

Saya melakukan ini yang memecahkan masalah untuk saya.

ActiveRecord::Base.connection.tables.each do |t|
  ActiveRecord::Base.connection.reset_pk_sequence!(t)
end

Saya menemukan reset_pk_sequence! dari utas ini. http://www.ruby-forum.com/topic/64428

Sebuah pie
sumber
4
Terima kasih, solusi terbaiknya. Setelah transfer database saya mengalami masalah yang sama.
Oleg Pasko
63
Atau yang setara satu baris (untuk tujuan salin / tempel konsol rel):ActiveRecord::Base.connection.tables.each { |t| ActiveRecord::Base.connection.reset_pk_sequence!(t) }
Raf
Tahu bagaimana ini tidak sinkron?
Tall Paul
25

Berdasarkan jawaban @Apie .

Anda dapat membuat tugas dan menjalankannya saat Anda membutuhkannya dengan:

rake database:correction_seq_id

Anda membuat tugas seperti ini:

rails g task database correction_seq_id

Dan di file yang dihasilkan ( lib/tasks/database.rake) letakkan:

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
inye
sumber
4

Kedengarannya seperti masalah database dan bukan masalah Rails. Mungkinkah database Anda memiliki seed identitas yang tidak tepat di idkolom Anda ? Untuk menguji coba lakukan beberapa penyisipan langsung ke database Anda dan lihat apakah ada perilaku yang sama.

mynameiscoffey
sumber
3
Mengapa suara negatif itu? Ini adalah perilaku persis yang terjadi jika Anda menyetel urutan kenaikan ke sesuatu yang lebih rendah dari nilai lain yang ada dan karena itu terkadang terjadi benturan saat memasukkan data. Poster tersebut sudah mengatakan ada data yang termasuk dalam kasus ini.
namakuiscoffey
Saya bisa memasukkan dengan baik. Setelah saya mendapatkan kesalahan ini, saya benar-benar dapat menjalankan tindakan yang sama lagi dan berhasil, jika id berikutnya dalam urutan belum diambil.
D-Nice
Sepertinya ini adalah situasi saya - saya mengalami masalah tetapi catatan berikutnya yang saya masukkan berfungsi dengan baik, jadi itu pasti telah memasukkan benih ke tempat yang tepat.
Ben Wheeler
3

Saya menyelesaikan masalah ini dengan mengikuti perintah.

Jalankan ini di konsol rel Anda

ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
Jigar Bhatt
sumber