Search code examples
ruby-on-railsapipaginationactive-model-serializersjson-api

How to encapsulating API response inside "data" keys and paginate them?


I am using active model serializers to serialize the users.

In my Seller controller I have,

def index
   seller = User.all.where(catagories: "seller")
   render json: seller, status: :ok,  status: :ok
end

UserSerializer class looks like this.

  attributes :id, :name, :email, :phone_number, :verified
  has_many :products
  has_one :address`

Output is also fair enough.

{
    "users": [
        {
            "id": 1,
            "name": "Craig Crist",
            "email": "adena_kiehn@greenfelder.com",
            "phone_number": "876.862.8760 x0096",
            "verified": true,
            "products": [
                {
                    "id": 1,
                    "name": "Direct Performance Transmitter",
                    "price": 1000,
                    "warranty": false,
                    "discount": 50,
                    "description": "Vel doloribus distinctio nihil rerum libero. Reprehenderit ratione cumque porro nesciunt. Id recusandae aut vel voluptatem aperiam hic deleniti voluptas."
                }
            ],
            "address": {
                "id": 1,
                "latitude": 41.022921,
                "longitude": -118.064638782714,
                "street_name": "Beattystr.",
                "city": "Hermannport"
            }
        }

but I need that response to be encapsulated inside a key called data.

data : {
        "users": [
            {
                "id": 1,
                "name": "Craig Crist",
                "email": "adena_kiehn@greenfelder.com",
                "phone_number": "876.862.8760 x0096",
                "verified": true,
                "products": [
                    {
                        "id": 1,
                        "name": "Direct Performance Transmitter",
                        "price": 1000,
                        "warranty": false,
                        "discount": 50,
                        "description": "Vel doloribus distinctio nihil rerum libero. Reprehenderit ratione cumque porro nesciunt. Id recusandae aut vel voluptatem aperiam hic deleniti voluptas."
                    }
                ],
                "address": {
                    "id": 1,
                    "latitude": 41.022921,
                    "longitude": -118.064638782714,
                    "street_name": "Beattystr.",
                    "city": "Hermannport"
                }
            }

I can achieve that by wrapping the data with data key in a hash like below so my index method looks like this.

 def index
   seller = User.all.where(catagories: "seller")
   render json:  { data: { user: seller } },  status: :ok
end

but after doing this, the relationships are not rendered in json.

{
    "data": {
        "user": [
            {
                "id": 1,
                "name": "Craig Crist",
                "email": "adena_kiehn@greenfelder.com",
                "phone_number": "876.862.8760 x0096",
                "verified": true,
                "avatar": "https://robohash.org/voluptatemsintnon.png?size=300x300",
                "badge": 3,
                "catagories": "seller",
                "rating": 1,
                "created_at": "2017-06-25T10:31:39.575Z",
                "updated_at": "2017-06-25T10:31:39.575Z"
            }

also I was using gem 'api-pagination' to paginate this array, but

after the user is encapsulated inside data, the api-pagination also stops working.

How can I achieve the desired output and have it paginated ?


Solution

  • Here are two of the ways to do as you wish:

    render json: User.all, adapter: :json_api
    

    or

    # in config/am_serializer.rb
    ActiveModelSerializers.config.adapter = :json_api
    
    # in controller
    render json: User.all
    

    Now response will be rendered as

    {
      "data": {
        "id": "1",
        "type": "profile",
        "attributes": {
          "name": "Julia"
        }
      }
    }
    

    The json_api adapter is designed to comply with the specification defined here http://jsonapi.org/

    Useful links:
    https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/serializers.md#other


    but that will change the response format to jsonapi. the response format of all api will be different. client app does not follow jsonapi standards

    try this, it should work

    render json: {data: ActiveModelSerializers::SerializableResource.new(User.all)}
    

    The default adapter would be json not json_api