Echte Eindeutigkeitsvalidierung

Jeder Hacker, der mit Ruby On Rails gearbeitet hat, ist mit ORM ActiveRecord vertraut. Wir werden eine der vorgeschlagenen Validierungen sofort diskutieren, nämlich Validierungen auf Eindeutigkeit, und warum das Juwel database_validations die Konsistenz Ihrer Datenbank spart.

Angenommen, Sie haben ein Benutzermodell mit Eindeutigkeit im E-Mail- Feld, d. H.

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

Möglicherweise wissen Sie bereits, dass diese Validierung die folgende Anforderung ausführt

 SELECT 1 FROM users WHERE email = $1 

Jedes Mal, wenn wir versuchen, einen Datensatz in der Datenbank zu speichern.

Dieser Ansatz hat mehrere Nachteile:

Erstens die Ausführung einer zusätzlichen Anforderung, und wenn im Modell mehrere Eindeutigkeitsüberprüfungen initialisiert werden, wird die Anforderung für jede von ihnen ausgeführt. Dies ist nicht effizient und erfordert auch Indizes, wenn diese Abfragen schnell ausgeführt werden sollen.

Zweitens garantiert diese Lösung aufgrund eines möglichen Wettlaufs um Daten keine Eindeutigkeit. Mehrere Wettbewerbsvorgänge können gleichzeitig feststellen, dass kein bestimmter Datensatz vorhanden ist, wodurch dieselben Daten gespeichert werden.

Natürlich können seltene Fälle mit Datenrennen durch Hinzufügen einer Eindeutigkeitsbeschränkung auf Datenbankebene gelöst werden. In diesem Fall wird jedoch kein Validierungsfehler angezeigt. Die Abfrage an die Datenbank wird einfach gelöscht und die gesamte Transaktion wird zurückgesetzt.

In dieser Situation hilft gem database_validations , wodurch die Kompatibilität zwischen Datenbankbeschränkungen und Validierungen gewährleistet wird.

Die Hauptbedeutung von Edelstein wird im folgenden Code dargestellt:

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


Daher versuchen wir, die Daten zu speichern. Wenn alle anderen Überprüfungen bestanden sind, wenn die Transaktion ausfällt und zurückgesetzt wird, analysieren wir den Fehler und weisen den errors unseres Objekts die richtigen Werte zu.

Nach Durchsicht der Dokumentation und der Benchmarks können wir den Schluss ziehen, dass dieses Juwel das Speichern von Datensätzen in der Datenbank mindestens zweimal beschleunigt.

Dank der Unterstützung von Datenbanken wie PostgreSQL , SQLite , MySQL und der Abwärtskompatibilität mit validates_db_uniqueness_of dauert das Ersetzen durch validates_db_uniqueness_of nur wenige Minuten.

Ein praktischer Matcher für RSpec ist ebenfalls sofort verfügbar:

 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 

Wenn Sie zu einer neuen Validierung wechseln, müssen Sie Einschränkungen hinsichtlich der Eindeutigkeit in der Datenbank haben. Wenn diese jedoch noch nicht vorhanden sind, zeigt gem dies beim Start der Anwendung an.

Der Edelstein wurde an einer Anwendung mit mehr als 100 Validierungen auf Einzigartigkeit unter mehr als 50 Modellen getestet.

Verwenden Sie Edelstein und teilen Sie Ihre Meinung. Jeder Beitrag zur Weiterentwicklung ist willkommen!

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


All Articles