- PVSM.RU - https://www.pvsm.ru -
Каждый рубист, поработавший с Ruby On Rails [1] знаком с ORM [2] ActiveRecord [3]. Обсудим одну из предложенных из коробки валидаций, а именно, валидации на уникальность, и почему database_validations [4] gem спасет консистенцию вашей базы данных.
Допустим, у вас есть модель пользователей с уникальностью на поле email, т.е.
class User < ApplicationRecord
validates :email, uniqueness: true
end
Вы, возможно, уже знаете, что данная валидация выполняет следующий запрос
SELECT 1 FROM users WHERE email = $1
каждый раз, когда мы пытаемся сохранить запись в базу данных.
У данного подхода, есть несколько недостатков:
Во-первых, исполнение дополнительного запроса, и в случае, если в модели инициализировано несколько валидаций на уникальность, запрос будет выполнен на каждую из них. Это не эффективно, а также требует наличие индексов, если мы хотим, чтобы данные запросы исполнялись быстро.
Во-вторых, данное решение не гарантирует уникальность из-за возможной гонки за данными [5]. Несколько конкурентных операций могут одновременно узнать об отсутствии конкретной записи, в следствии чего, сохранить одни и те же данные.
Конечно, редкие случаи с гонкой данных возможно разрешить добавив ограничение на уникальность на уровне базы данных. Но в данном случае, вы не получите ошибку валидации, запрос к БД просто упадет и вся транзакция откатится.
В этой ситуации поможет gem database_validations [4], который предоставляет совместимость между ограничениями в базе данных и валидациями.
Ознакомившись с документацией [6] и бенчмарками [7], можно прийти к выводу, что данный gem ускорит процесс сохранения записей в базу данных минимум в два раза.
Благодаря поддержке таких баз данных, как PostgreSQL, SQLite, MySQL и обратной совместимости с validates_uniqueness_of, процесс замены на validates_db_uniqueness_of занимает считанные минуты.
Удобный matcher для RSpec также присутствует из коробки:
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
При переходе на новую валидацию, вам необходимо иметь ограничения на уникальность в базе данных, но если их еще нет, gem об этом укажет во время запуска приложения.
Гем протестирован на приложении с 100+ валидациями на уникальность среди 50+ моделей.
Используйте гем и делитесь мнением. Любой вклад в дальнейшее развитие приветствуется!
Автор: djezzzl
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ruby/300453
Ссылки в тексте:
[1] Ruby On Rails: https://rubyonrails.org/
[2] ORM: https://ru.wikipedia.org/wiki/ORM
[3] ActiveRecord: https://github.com/rails/rails/tree/master/activerecord
[4] database_validations: https://github.com/toptal/database_validations
[5] гонки за данными: https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%B3%D0%BE%D0%BD%D0%BA%D0%B8
[6] документацией: https://github.com/toptal/database_validations#databasevalidations
[7] бенчмарками: https://github.com/toptal/database_validations#benchmark-code
[8] Источник: https://habr.com/post/431298/?utm_campaign=431298
Нажмите здесь для печати.