Использование рельсов 7.1.3.4 и Ruby 3.3.4
У меня есть этот код в контроллере:
render json: item.item_tags.map do |item_tag|
{
things_count: item_tag.tag.things.count,
other_count: item_tag.tag.other_association.count,
tag: {
id: item_tag.tag.id,
name: item_tag.tag.name,
slug: item_tag.tag.slug,
things: ThingSerializer.new.index(item_tag.tag.things),
}
}
end
ThingSerializer
здесь также есть map
, который проходит и сериализует все прошедшие вещи.
Предполагается, что он вернет список на основе значения map
.
Однако он возвращает список по умолчанию item_tags
, то есть:
[{
"id": 236,
"status": "draft",
"position": 0,
"item_id": 234,
"tag_id": 123,
"inserted_at": "2024-03-19T10:23:56.000+03:00",
"updated_at": "2024-03-19T10:23:56.000+03:00"
}]
Но если я сделаю это:
actual_json = item.item_tags.map do |item_tag|
{
things_count: item_tag.tag.things.count,
other_count: item_tag.tag.other_association.count,
tag: {
id: item_tag.tag.id,
name: item_tag.tag.name,
slug: item_tag.tag.slug,
things: ThingSerializer.new.index(item_tag.tag.things),
}
}
end
render json: actual_json
Это работает так, как ожидалось.
Почему именно так?
ПС. Я делаю подобные вещи в других контроллерах, и все работает так, как ожидалось. Только здесь он не возвращает ожидаемое значение.
Почему бы вам не показать нам свои модели, сериализатор, ожидаемый результат JSON и т. д. и не позволить нам предложить вам подход, который действительно работает? Почти каждая строка здесь является нарушением закона Деметры, и у вас n+2 запроса к базе данных. xyproblem.info
Я ценю предупреждения о запросах N+1. Проблема в том, что во втором примере ключи json отображаются так, как они определены в коде (things_count,other_count, tag и т. д.). Однако в первом примере я получаю совершенно несвязанные ключи (id, статус, позиция и т. д.). Единственная разница в том, что я сначала сохраняю его в переменной, прежде чем визуализировать ответ.
Ваш блок передается render
, который ничего не делает:
render json: [1,2,3].map do |i|
{i => i}
end
#=> [1,2,3]
Вам нужно либо использовать {}
вместо do end
, либо добавить скобки:
render json: [1,2,3].map { |i|
{i => i}
}
#=> [{"1":1},{"2":2},{"3":3}]
render(
json: [1,2,3].map do |i|
{i => i}
end
)
#=> [{"1":1},{"2":2},{"3":3}]
Убедитесь, что вы используете
map
, а неeach
. Кстати, у вас здесь N+1