Хабрахабр

Как прокачать belongs_to чтобы работал в два раза быстрее (database_validations gem)

В данной статье, я покажу почему нужно использовать db_belongs_to из database_validations гема вместо привычного нам belongs_to.

Но знаете ли вы, что инициализация связи с помощь belongs_to в вашей модели также добавляет валидацию на существование связи. Я уверен, что большинство из вас знакомо с belongs_to из ORM ActiveRecord. Это происходит потому, что 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 включал такие же ошибки.

Данный гем уже включал в себя validates_db_uniqueness_of, который понравился людям (пост на хабре) и теперь имеет db_belongs_to, который очень легко внедрить в ваш проект. Чтобы не писать всю обработку самостоятельно, вам пригодится database_validations гем. db_belongs_to улучшает производительность и гарантирует целостность данных.

Метод делает несколько вещей за вас:

  • Проверяет существование правильного ограничения внешнего ключа в базе данных во время запуска приложения;
  • Парсит исключения базы данных и предоставляет соответствующие ошибки для errors вашего объекта;
  • Исключает необходимость исполнения лишних SQL запросов к базе данных;

Данный гем уже протестирован в production окружении и показал себя очень хорошо. Я рекомендую вам использовать database_validations в ваших проектах. чем больше вы используете его, тем больше сохраняете, ознакомьтесь с групповыми бенчмарками для деталей. Несмотря на его простоту реализации, он может сильно улучшить производительность вашего проекта, т.к.

Признательны за любой вклад в проект! Любые отзывы приветствуются!

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»