Anda dapat menggunakan validates
untuk memvalidasi uniqueness
pada satu kolom:
validates :user_id, uniqueness: {scope: :friend_id}
Sintaks untuk validasi pada beberapa kolom serupa, tetapi Anda harus menyediakan array bidang sebagai gantinya:
validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}
Namun , pendekatan validasi yang ditunjukkan di atas memiliki kondisi balapan dan tidak dapat memastikan konsistensi. Perhatikan contoh berikut:
catatan tabel database seharusnya unik oleh n bidang;
beberapa ( dua atau lebih ) permintaan bersamaan, masing-masing ditangani oleh proses yang terpisah ( server aplikasi, server pekerja latar belakang atau apa pun yang Anda gunakan ), mengakses database untuk menyisipkan catatan yang sama dalam tabel;
setiap proses secara paralel memvalidasi jika ada catatan dengan bidang n yang sama ;
validasi untuk setiap permintaan berhasil dilewati, dan setiap proses membuat catatan dalam tabel dengan data yang sama.
Untuk menghindari perilaku semacam ini, kita harus menambahkan batasan unik ke tabel db. Anda dapat mengaturnya dengan add_index
helper untuk satu (atau beberapa) bidang dengan menjalankan migrasi berikut:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :table_name, [:field1, ... , :fieldn], unique: true
end
end
Peringatan : bahkan setelah Anda menetapkan batasan unik, dua atau lebih permintaan bersamaan akan mencoba untuk menulis data yang sama ke db, tetapi alih-alih membuat rekaman duplikat, ini akan menimbulkan ActiveRecord::RecordNotUnique
pengecualian, yang harus Anda tangani secara terpisah:
begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end