Ruby: ActiveRecord (ORM)
Теория: Связи
Связи
Сущности предметной области не существуют сами по себе. Они часто зависят друг от друга. На уровне базы данных такие связи задаются через внешние ключи или даже промежуточные таблицы, как в случае связи «многие ко многим».
ORM использует эти ключи для работы со связями. Он добавляет множество полезных методов, которые упрощают работу с зависимыми сущностями: выборкой, добавлением, модификацией и удалением.
Представим, что мы создаем блог, и нам понадобится сущность Post. Пользователи связаны с постами «один ко многим»:
- Один пользователь может быть автором многих постов
- У одного поста всегда один автор
Структура
Для поддержки такой связи при создании таблицы постов нужно добавить внешний ключ на таблицу пользователей. Далее приведен пример файла миграции, который создает таблицу posts с внешним ключом creator таблицы users. Что такое миграции и как с ними работать, мы разберем в следующих уроках.
Рассмотрим пример:
По умолчанию ActiveRecord не воспринимает внешние ключи как что-то особенное. Она требует явного указания связи на уровне моделей. Для этого в каждой из моделей определяется специальный метод, через который будет происходить взаимодействие между связанными сущностями. Имя этого метода произвольно. Оно выбирается так, чтобы лучше отражать суть связи: у поста есть автор, у каждого автора есть посты.
В следующем примере мы используем методы belongs_to и has_many для установки связей между моделями. При этом используется параметр class_name для указания класса, с которым устанавливается связь. Это особенно полезно в случаях, когда имя ассоциации не совпадает с именем соответствующего класса.
В данном контексте belongs_to и has_many обозначают «принадлежит к» и «имеет много» соответственно.
Так это выглядит на практике:
В этом примере Post принадлежит User, который обозначен как creator.
А здесь каждый User «имеет много» posts, связанных через внешний ключ creator_id.
Метод has_many также поддерживает соглашение для определения имени внешнего ключа. Только здесь оно определяется не по имени метода, а по имени модели, в которой описывается связь. Для модели User это будет user_id. В нашем случае такая логика не работает, поэтому имя свойства указано явно.
CRUD
Теперь ActiveRecord знает о связях и позволяет работать с ними напрямую:
Обращение к коллекции зависимых сущностей возвращает специальный объект, который может использоваться как массив.
Есть и другой способ взаимодействовать с зависимостями. Вызов posts как метода позволяет управлять этой коллекцией, например, удалить или добавить новый пост:
То же самое происходит и с другой стороны связи:
При работе со связями важно переключиться от мышления через таблицы и ключи к сущностям и связям. Технически это значит, что код опирается на сами сущности, а не их идентификаторы:
Выборки
Все типы связей в ActiveRecord поддерживают построение запросов на выборку:

