- PVSM.RU - https://www.pvsm.ru -
В данной статье, я покажу почему нужно использовать db_belongs_to
из database_validations [1] гема вместо привычного нам belongs_to
.
Я уверен, что большинство из вас знакомо с belongs_to
из ORM ActiveRecord. Но знаете ли вы, что инициализация связи с помощь belongs_to
в вашей модели также добавляет валидацию на существование связи. Это происходит потому, что belongs_to
имеет опцию optional: false
по умолчанию.
Таким образом, каждый раз когда вы сохраняете новый объект или обновляете существующий, вы выполняете дополнительный SQL SELECT запрос на каждую из ваших связей.
Пример
class User < ActiveRecord::Base
belongs_to :company
belongs_to :country
end
user = User.first
user.update(some_field: 'something')
# В первую очередь сделает два дополнительных запроса SELECT, чтобы узнать, что связи `company` и `country` существуют
Вам также следует знать, что данный подход не гарантирует целостность базы данных, т.к. связи могут быть в дальнейшем удалены (в последующих или параллельных запросах) без каких-либо проблем.
user.update(...)
user.company.destroy!
=> команда будет выполнена без ошибок, таким образом, в базе данных будет храниться пользователь без связи с компанией, что нарушает целостность нашей базы данных (если изначально не было задумано обратное)
Чтобы решить данную проблему, вы можете добавить соответствующее ограничение внешнего ключа (foreign key constraint) в вашу базу данных. Имея данное ограничение, вы всегда будете уверены, что данная связь существует.
Что насчет производительности? Зачем нам делать SELECT запросы к базе данных, если мы уже уверены, что целостность данных будет соблюдена (с использованием ограничения внешнего ключа)?
Ответ прост — не нужно. Но, чтобы это стало возможным, нам нужно решить проблему обработки исключения ActiveRecord::InvalidForeignKey
, которое мы получаем, когда пытаемся сохранить отсутствующую в базе данных связь. Это необходимо, чтобы иметь такое же поведение, как с belongs_to
, чтобы errors
включал такие же ошибки.
Чтобы не писать всю обработку самостоятельно, вам пригодится database_validations гем [1]. Данный гем уже включал в себя validates_db_uniqueness_of
, который понравился людям (пост на хабре [2]) и теперь имеет db_belongs_to
, который очень легко внедрить в ваш проект. db_belongs_to
улучшает производительность и гарантирует целостность данных.
Метод делает несколько вещей за вас:
errors
вашего объекта;Я рекомендую вам использовать database_validations [1] в ваших проектах. Данный гем уже протестирован в production окружении и показал себя очень хорошо. Несмотря на его простоту реализации, он может сильно улучшить производительность вашего проекта, т.к. чем больше вы используете его, тем больше сохраняете, ознакомьтесь с групповыми бенчмарками [3] для деталей.
Любые отзывы приветствуются! Признательны за любой вклад в проект!
Автор: djezzzl
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ruby/300853
Ссылки в тексте:
[1] database_validations: https://github.com/toptal/database_validations
[2] пост на хабре: https://habr.com/post/431298/
[3] групповыми бенчмарками: https://github.com/toptal/database_validations#composed-benchmarks
[4] Источник: https://habr.com/post/431734/?utm_source=habrahabr&utm_medium=rss&utm_campaign=431734
Нажмите здесь для печати.