Что такое ActiveRecord::Relation?

Relation описывает запрос Active Record и позволяет наращивать условия до загрузки данных. После загрузки тот же объект повторно использует полученные записи.

Короткий ответ

Что ответить на собеседовании

ActiveRecord::Relation — объект запроса: where, order и limit позволяют собрать его лениво, а each, to_a или load загружают записи. Загруженный relation хранит их и не выполняет новый SELECT при каждом повторном обходе. reload заново загружает результат, reset сбрасывает состояние загрузки. count, exists? и pluck имеют собственную логику и могут выполнять отдельные SQL-запросы.

Подробный разбор

Ответ с пояснениями

ActiveRecord::Relation представляет запрос к модели: условия, сортировку, ограничения и другие параметры. Это не просто массив уже полученных объектов. Обычные вызовы where, order, limit возвращают relation, поэтому их можно объединять в цепочку до чтения данных. Интерфейс запросов Rails

Предположим, у User есть поля status, role и email:

active = User.where(status: 'active')
admins = active.where(role: 'admin').order(:id).limit(20)

admins.each { |user| puts user.email } # загрузка записей
admins.each { |user| puts user.id }    # повторный обход тех же записей
p admins.loaded?                      # true

Создание цепочки само по себе обычно не загружает строки. Чтение через each или to_a запускает загрузку, а load позволяет выполнить её явно, сохранив relation как возвращаемое значение. В консоли вывод объекта может вызвать запрос через inspect, что иногда создаёт впечатление отсутствия ленивости.

Загруженный relation хранит записи: второй обход того же admins использует его массив объектов. Это не означает, что он автоматически замечает изменения БД. reset очищает состояние загрузки без немедленного чтения; reload сбрасывает его и запускает загрузку заново. Не следует смешивать это хранение записей с отдельным механизмом SQL query cache. Relation: load, reset и reload

Цепочка обычно создаёт новые relation: добавление условия к active не превращает исходный объект в выборку только администраторов. При этом не все методы читают сохранённые записи одинаково. count без блока обычно выполняет SQL-агрегацию, exists? — отдельную проверку наличия. Они не обязаны использовать уже загруженный массив. Calculations, exists?

pluck возвращает значения столбцов без создания моделей при обычной SQL-загрузке, но для загруженного relation может взять доступные атрибуты из памяти. Поэтому утверждения «любой доступ выполняет запрос» и «после загрузки SQL больше невозможен» одинаково неверны. Поведение pluck

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку