Validasi keunikan sejati

Setiap peretas yang telah bekerja dengan Ruby On Rails terbiasa dengan ORM ActiveRecord . Kami akan membahas salah satu validasi yang diusulkan di luar kotak, yaitu, validasi untuk keunikan, dan mengapa permata database_validations akan menyimpan konsistensi database Anda.

Katakanlah Anda memiliki model pengguna dengan keunikan di bidang email , mis.

class User < ApplicationRecord validates :email, uniqueness: true end 

Anda mungkin sudah tahu bahwa validasi ini melakukan permintaan berikut

 SELECT 1 FROM users WHERE email = $1 

setiap kali kami mencoba menyimpan catatan dalam basis data.

Pendekatan ini memiliki beberapa kelemahan:

Pertama , eksekusi permintaan tambahan, dan jika beberapa validasi keunikan diinisialisasi dalam model, permintaan akan dieksekusi untuk masing-masing. Ini tidak efisien, dan juga memerlukan indeks jika kita ingin query ini dieksekusi dengan cepat.

Kedua , solusi ini tidak menjamin keunikan karena kemungkinan perlombaan untuk data . Beberapa operasi kompetitif dapat secara bersamaan belajar tentang tidak adanya catatan khusus, sebagai akibatnya, untuk menyimpan data yang sama.

Tentu saja, kasus yang jarang terjadi dengan perlombaan data dapat diatasi dengan menambahkan kendala keunikan di tingkat basis data. Tetapi dalam kasus ini, Anda tidak akan mendapatkan kesalahan validasi, kueri ke database hanya akan jatuh dan seluruh transaksi akan dibatalkan.

Dalam situasi ini, gem database_validations akan membantu, yang menyediakan kompatibilitas antara pembatasan dan validasi basis data.

Arti utama permata disajikan dalam kode berikut:

 def save(options = {}) ActiveRecord::Base.connection.transaction(requires_new: true) { super } rescue ActiveRecord::RecordNotUnique => e Helpers.handle_unique_error!(self, e) false end 


Jadi, kami mencoba untuk menyimpan data, jika semua validasi lain dilewatkan, jika transaksi jatuh dan gulung balik, kami mengurai kesalahan dan menetapkan nilai yang benar untuk errors objek kami.

Setelah meninjau dokumentasi dan tolok ukur , kita dapat menyimpulkan bahwa permata ini akan mempercepat proses menyimpan catatan ke database setidaknya dua kali.

Berkat dukungan database seperti PostgreSQL , SQLite , MySQL , dan kompatibilitas mundur dengan validates_uniqueness_of , proses penggantian dengan validates_db_uniqueness_of membutuhkan waktu beberapa menit.

Pencocokan berguna untuk RSpec juga hadir di luar kotak:

 specify do expect(described_class) .to validate_db_uniqueness_of(:field) .with_message('duplicate') .with_where('(some_field IS NULL)') .scoped_to(:another_field) .with_index(:unique_index) end 

Saat beralih ke validasi baru, Anda harus memiliki batasan pada keunikan dalam database, tetapi jika belum ada, gem akan menunjukkan ini saat aplikasi dimulai.

Permata diuji pada aplikasi dengan 100+ validasi untuk keunikan di antara 50+ model.

Gunakan permata dan bagikan pendapat Anda. Setiap kontribusi untuk pengembangan lebih lanjut dipersilahkan!

Source: https://habr.com/ru/post/id431298/


All Articles