jsonapi-rails icon indicating copy to clipboard operation
jsonapi-rails copied to clipboard

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

Open caseyprovost opened this issue 6 years ago • 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": "[email protected]",
        "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": "[email protected]",
        "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"
  }
}

caseyprovost avatar Apr 27 '18 19:04 caseyprovost

First, class_name: 'User' has no effect.

Not sure why the included section is left out though.

beauby avatar Jun 13 '18 14:06 beauby

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

dduqueti avatar Nov 14 '18 20:11 dduqueti

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

dduqueti avatar Nov 15 '18 21:11 dduqueti

@dduqueti Check out these gists:

  • https://gist.github.com/caseyprovost/f1e7cc2348d8d64b8665a88c4f68099f (pagination logic)
  • https://gist.github.com/caseyprovost/d72997fbada92ee6d77313cff5e1c470 (using pagination logic)

caseyprovost avatar Nov 17 '18 17:11 caseyprovost

@dduqueti Join the slack channel and DM me :) I can help you through this.

Slack -> https://join.slack.com/t/jsonapi-suite/shared_invite/enQtMjkyMTA3MDgxNTQzLWVkMDM3NTlmNTIwODY2YWFkMGNiNzUzZGMzOTY3YmNmZjBhYzIyZWZlZTk4YmI1YTI0Y2M0OTZmZGYwN2QxZjg

caseyprovost avatar Nov 17 '18 17:11 caseyprovost

@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.

kohheepeace avatar Dec 09 '18 17:12 kohheepeace