0

Doing in Rails what may require a more complex/creative solution, but basically using Grape, active_model_serializers (AMS), and grape-kaminari to return an index route (list) of User objects, and I'd like to be able to use the advantages of AMS with caching and easily serializing objects, but customize the JSON response.

Here's Grape:

module API
  module V1
    class Users < Grape::API
      include API::V1::Defaults
      include Grape::Kaminari

      resource :users do
         paginate per_page: 18
         get do
           users = User.all
           paginate users
         end
      end
    end
  end
end

And AMS:

class UserSerializer < ActiveModel::Serializer
  cache key: 'user', expires_in: 3.hours
  attributes :id, :firstname, :lastname, :email, :username
end

Ideal Response in JSON:

{
  users: [
    {
      id: 1,
      firstname: "Daniel",
      lastname: "Archer,
      email: "daniel@archer.co",
      username: "dja"
     },
    {
      id: 2,
      firstname: "Fakey",
      lastname: "McFakerson,
      email: "fake@fake.io",
      username: "fake"
     }
  ],
  extras: {
    user_count: 300,
    new_users_last_5_days: 10,
    new_users_last_30_days: 25
  }
}

What I'd like to happen (and having trouble with) is to paginate the amount of users in the JSON response, but include some extras that are related to the entire collection of Users. For example, I may have 300 Users, but I only want to return the first 18 users (or however many based on params per_page and page), and extra data on the entire collection.

1 Answers1

0

With Grape::Entity you can present multiple values.

paginate users

just presents the selected page of users. You can add another present just after that:

present :extras, {user_count: User.count, ...}

To Answer your comment:
I'm using a similar setup and have a response that is paginated with kaminary and extended with extra data:

get do
  ...
  present :statistics, statistics, with: API::Entities::Statistics
  present :refresh_time, Setting.list_refresh_time
  present :users, @users.page(params[:page]).per(18), with: API::Entities::User
end

With vanilla Grape, a data structure is returned, that is converted dependent of the output format, i.e. with .to_json. So you can return a Hash:

get do
  ...
  { statistics: some_statistics, 
    users: @users.page(params[:page]).per(18)
  }
end
Martin M
  • 8,430
  • 2
  • 35
  • 53