Validation de l'unicité véritable

Chaque pirate informatique qui a travaillé avec Ruby On Rails est familier avec ORM ActiveRecord . Nous discuterons de l'une des validations proposées hors de la boîte, à savoir, les validations pour l'unicité, et pourquoi la gem de database_validations sauvera la cohérence de votre base de données.

Supposons que vous ayez un modèle utilisateur unique dans le champ e - mail , c'est-à-dire

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

Vous savez peut-être déjà que cette validation effectue la demande suivante

 SELECT 1 FROM users WHERE email = $1 

chaque fois que nous essayons de sauvegarder un enregistrement dans la base de données.

Cette approche présente plusieurs inconvénients:

Tout d'abord , l'exécution d'une requête supplémentaire, et si plusieurs validations d'unicité sont initialisées dans le modèle, la requête sera exécutée pour chacune d'entre elles. Ce n'est pas efficace et nécessite également des index si nous voulons que ces requêtes s'exécutent rapidement.

Deuxièmement , cette solution ne garantit pas l'unicité en raison d'une éventuelle course aux données . Plusieurs opérations concurrentielles peuvent apprendre simultanément l'absence d'un enregistrement spécifique, ce qui permet de conserver les mêmes données.

Bien sûr, de rares cas de course aux données peuvent être résolus en ajoutant une contrainte d'unicité au niveau de la base de données. Mais dans ce cas, vous n'obtiendrez pas d'erreur de validation, la requête vers la base de données tombera simplement et toute la transaction sera annulée.

Dans cette situation, gem database_validations vous aidera, ce qui assure la compatibilité entre les restrictions de base de données et les validations.

La signification principale de gem est présentée dans le code suivant:

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


Ainsi, nous essayons de sauvegarder les données, si toutes les autres validations sont réussies, si la transaction tombe et revient en arrière, nous analysons l'erreur et attribuons les valeurs correctes aux errors notre objet.

Après avoir examiné la documentation et les références , nous pouvons conclure que cette gemme accélérera le processus d'enregistrement des enregistrements dans la base de données au moins deux fois.

Grâce à la prise en charge de bases de données telles que PostgreSQL , SQLite , MySQL et à la rétrocompatibilité avec validates_uniqueness_of , le processus de remplacement par validates_db_uniqueness_of prend quelques minutes.

Un matcher pratique pour RSpec est également présent hors de la boîte:

 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 

Lorsque vous passez à une nouvelle validation, vous devez avoir des restrictions sur l'unicité dans la base de données, mais si elles ne sont pas déjà là, gem l'indiquera au démarrage de l'application.

La gemme a été testée sur une application avec plus de 100 validations pour l'unicité parmi plus de 50 modèles.

Utilisez gem et partagez votre opinion. Toute contribution à un développement ultérieur est la bienvenue!

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


All Articles