jsonapi-rb/jsonapi-rails

"included" key missing from response when object is same type

caseyprovost opened this issue ยท 6 comments

Working through implementing includes I have discovered what appears to be a bug. All my other code like this works as expected and the only difference I can find is that the association is the same class as the requested object.

Controller
users = User.includes(:managers, :direct_reports).page(params[:page]).per(params[:per_page])
render jsonapi: users,
             include: ['managers', 'direct_reports'],
             links: pagination_links(users, User)
Serializer
class SerializableUser < JSONAPI::Serializable::Resource
  type 'users'
  
  belongs_to :role
  belongs_to :parent
  has_many :managers, class_name: 'User'
  has_many :direct_reports, class_name: 'User'
end

The response looks nearly correct, except the includes are missing at the end. I have provided a sample below.

{
  "data": [
    {
      "id": "1",
      "type": "users",
      "attributes": {
        "name": "Meghan Wilkinson",
        "email": "mauricio@lang.com",
        "threshold": null
      },
      "relationships": {
        "direct_reports": {
          "links": {
            "self": "http://localhost:3000/v1/users/1/relationships/direct_reports",
            "related": "http://localhost:3000/v1/users"
          },
          "data": []
        },
        "managers": {
          "links": {
            "self": "http://localhost:3000/v1/users/1/relationships/managers",
            "related": "http://localhost:3000/v1/users"
          },
          "data": []
        }
      }
    },
    {
      "id": "2",
      "type": "users",
      "attributes": {
        "name": "Dora Nitzsche",
        "email": "albin.legros@waters.io",
        "threshold": null
      },
      "relationships": {
        "parent": {
          "meta": {
            "included": false
          }
        },
        "role": {
          "meta": {
            "included": false
          }
        },
        "direct_reports": {
          "links": {
            "self": "http://localhost:3000/v1/users/2/relationships/direct_reports",
            "related": "http://localhost:3000/v1/users"
          },
          "data": [
            {
              "type": "users",
              "id": "5"
            }
          ]
        },
        "managers": {
          "links": {
            "self": "http://localhost:3000/v1/users/2/relationships/managers",
            "related": "http://localhost:3000/v1/users"
          },
          "data": [
            {
              "type": "users",
              "id": "4"
            }
          ]
        }
      }
    }
  ],
  "links": {
    "self": "http://localhost/v1/users?page=1&per_page=50",
    "first": "http://localhost/v1/users?page=1&per_page=50",
    "prev": null,
    "next": null,
    "last": "http://localhost/v1/users?page=1&per_page=50"
  },
  "jsonapi": {
    "version": "1.0"
  }
}

First, class_name: 'User' has no effect.

Not sure why the included section is left out though.

@caseyprovost I'm using included and fields and somehow every inner relationships key is missing ๐Ÿค” . Did you found anything?

@caseyprovost could you share your pagination_links implementation please? Trying to add pagination but I don't find any docs.

@dduqueti Hi, I encountered same issue, For example Category has_many SubCategories.

categories = Category.includes(:sub_categories).all  # this is the problem line
render jsonapi: categories, include: [:sub_categories]

The result of jsonapi does not have included data

*Expected Result

"data": [
  Category1
  Category2
  Category3
],
"included": [
  SubCategory1-1
]

*Real Result (SubCategory1-1 is not be included in Category1)

"data": [
  Category1
  Category2
  Category3
  SubCategory1-1
]

*Solution

# only render the parent Category
categories = Category.includes(:sub_categories).all.where(parent_id: nil)
render jsonapi: categories, include: [:sub_categories]

*Why not included ?
https://jsonapi.org/format/#document-compound-documents

compound document MUST NOT include more than one resource object for each type and id pair.

In my example SubCategory is already appeared in the data, so not appeared in included to avoid duplicate.