Без добавления каких-либо драгоценных камней:
def index
boats = Boat.includes(:year)
render json: {
boats: boats.as_json(include: { year: { only: :name } }),
numTotalBoats: boats.count
}
end
В какой-то момент я считаю, что вам следует использовать автономные сериализаторы:
Примечание : в зависимости от того,Если вы используете гем нумерации страниц или нет, вам может потребоваться изменить .count
вызовов ниже на .total_count
(для Каминари) или что-то еще, что будет правильно считывать счет из нумерации страниц.
Я рекомендую использовать Сериализаторы ActiveModel и вот как это будет сделано для вашего случая.
Начните с добавления камня в Gemfile:
gem 'active_model_serializers', '~-> 0.10'
Перезапишите адаптер в config / initializers / active_model_serializer.rb:
ActiveModelSerializers.config.adapter = :json
Определите сериализаторы для ваших моделей,
# app/serializers/boat_serializer.rb
class BoatSerializer < ActiveModel::Serializer
attributes :name
has_one :year
end
# app/serializers/year_serializer.rb
class YearSerializer < ActiveModel::Serializer
attributes :name
end
И, наконец, в вашем контроллере:
boats = Boat.includes(:year)
render json: boats, meta: boats.count, meta_key: "numTotalBoats"
И вы достигнете:
{
"boats": [
{
"name": "Boaty McBoatFace",
"year": {
"name": "2018"
}
},
{
"name": "Titanic",
"year": {
"name": "1911"
}
}
],
"numTotalBoats": 2
}
Добавление количества в каждом контроллере индекса немного утомительнотак что я обычно заканчиваю тем, что определяю свои собственные адаптеры или сериализаторы коллекций, чтобы позаботиться об этом автоматически (протестировано с Rails 5, а не 4).
# lib/active_model_serializers/adapter/json_extended.rb
module ActiveModelSerializers
module Adapter
class JsonExtended < Json
def meta
if serializer.object.is_a?(ActiveRecord::Relation)
{ total_count: serializer.object.count }
end.to_h.merge(instance_options.fetch(:meta, {})).presence
end
end
end
end
# config/initializers/active_model_serializer.rb
ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonExtended
# make sure to add lib to eager load paths
# config/application.rb
config.eager_load_paths << Rails.root.join("lib")
И теперь ваше действие индекса может выглядеть следующим образом
def index
boats = Boat.includes(:year)
render json: boats
end
И вывод:
{
"boats": [
{
"name": "Boaty McBoatFace",
"year": {
"name": "2018"
}
},
{
"name": "Titanic",
"year": {
"name": "1911"
}
}
],
"meta": {
"total_count": 2
}
}
Я думаю, что немного проще проанализировать этот счетчик для разных конечных точек, и вы получите его автоматически при ответе с коллекцией, так что ваши контроллеры будутнемного проще.