Хинт по работе со связанными данными на фронтенде

Казалось бы, банальная задача: манипулировать в SPA списком (допустим) фотографий, которые лайкнул текущий юзер. Добавляем в контроллер /api/users.json что-то вроде to_json(with: liked_photos) и получаем вместе с текущим юзером все айдишники лайкнутых им фоток на фронтенде. Можем показать их списком, в ряд, галереей, рандомно, как угодно. Вывести счётчик, сортануть и тэ дэ.

И всё круто до тех пор, пока…

Пока перед нами не встанет задача – снять (удалить) лайк той или иной фотки. А, собственно, как? Понятно, что у нас из-коробки растёт REST API, которое ожидает HTTP DELETE по адресу /api/likes/{ID}.json, но где взять этот айдишник? У нас-то его нет…

Начинающий разработчик начнёт городить особый метод API, принимающий два параметра { user_id, photo_id } и удаляющий этот несчастный лайк. Однако я настаиваю, что есть более правильный и более чистый (с точки зрения clean code) способ работы с такими данными.

Описанная ситуация неверна изначально. У вас не должно быть метода, отдающего лайкнутые фотки внутри юзера. Оставьте юзера в покое. У вас должен быть метод /api/likes.json, отдающий объекты-лайки примерно такой структуры:

{
user: { объект “кто лайкнул” },
liked: { объект “что лайкнуто” }
}

Собственно так оно и хранится в БД (лайк – это many-to-many сущность связи), то есть метод фактически есть “из-коробки”. И вот его уже можно фильтровать запросом: дай мне только лайкнутые объекты такого-то юзера, или дай мне объекты только такого типа (фотки, мероприятия, пользователи и тэ дэ).

Оффтопик: замечу, что с точки зрения нагрузки на сервер это запрос категории plain – простой селект из одной таблицы, совсем без условий или с простыми where, которые решаются на индексах. В отличие от попыток запихать информацию в юзера, наверняка потребующих джойнов.

И на выводе вы получаете именно правильные, полноценные данные, которые вам нужны: время создания этого лайка, айдишник лайка (для отсылки запроса на удаление), какие-то мета-данные если они есть (что-нибудь вроде ID модератора, который отревьюил этот лайк). А из атрибута liked уже достаёте всё, что вам нужно для отображения объекта: ID фотки, её заголовок, имя автора и всё такое прочее.