ash-project / ash_json_api

The JSON:API extension for the Ash Framework
https://hexdocs.pm/ash_json_api
MIT License
63 stars 43 forks source link

`includes` for `related` routes generates an error #174

Closed sevenseacat closed 5 months ago

sevenseacat commented 5 months ago

Describe the bug

I think this should be permitted by the JSON API spec, and the input validator permits it, but throws an error when attempting to access the relationship.

To Reproduce

An API defined on a domain:

  json_api do
    prefix "/api"

    routes do
      base_route "/artists", Tunez.Music.Artist do
        get :read
        index :search
        post :create
        patch :update
        delete :destroy
        related :albums, :read, primary?: true
      end
    end
  end

The Tunez.Music.Artist resource:

  json_api do
    type "artist"
    includes [:albums]
  end

  relationships do
    has_many :albums, Tunez.Music.Album do
      public? true
    end
  end

The Tunez.Music.Album resource:

  json_api do
    type "album"
    includes [:tracks]
  end

  relationships do
    has_many :tracks, Tunez.Music.Track do
      public? true
    end
  end

The Tunez.Music.Track resource:

  json_api do
    type "track"
  end

Trying to access a URL like the following:

http://localhost:4000/api/artists/{artist_id}/albums?include=tracks

(Including tracks for an artist's albums)

Generates an error:

[error] something_went_wrong: SomethingWentWrong | Raised error: e6eb83b4-31d2-4f24-a121-7d115c57c9f6

** (Ash.Error.Load.NoSuchRelationship) No such relationship Tunez.Music.Artist.tracks
    (elixir 1.17.0) lib/process.ex:864: Process.info/2
    (ash 3.0.13) lib/ash/error/load/no_such_relationship.ex:5: Ash.Error.Load.NoSuchRelationship.exception/1
    (ash 3.0.13) lib/ash/query/query.ex:2531: anonymous fn/3 in Ash.Query.do_validate_load/3
    (elixir 1.17.0) lib/enum.ex:4353: Enum.flat_map_list/2
    (ash 3.0.13) lib/ash/query/query.ex:2501: Ash.Query.validate_load/3
    (ash 3.0.13) lib/ash/query/query.ex:2490: Ash.Query.load_relationship/2

It does return valid JSON to the client, but possibly with too much information:

{
  "errors": [
    {
      "code": "something_went_wrong",
      "id": "e6eb83b4-31d2-4f24-a121-7d115c57c9f6",
      "status": "400",
      "title": "SomethingWentWrong",
      "detail": "Raised error: e6eb83b4-31d2-4f24-a121-7d115c57c9f6\n\n** (Ash.Error.Load.NoSuchRelationship) No such relationship Tunez.Music.Artist.tracks\n    (elixir 1.17.0) lib/process.ex:864: Process.info/2\n    (ash 3.0.13) lib/ash/error/load/no_such_relationship.ex:5: Ash.Error.Load.NoSuchRelationship.exception/1\n ...

Expected behavior

The tracks should be returned as part of the relationship data, ie.

(This is without include=tracks)

{
  "data": [
    {
      "attributes": {
        "name": "Eternal Tides",
        "cover_image_url": "/images/albums/crystal_cove/eternal_tides.png",
        "artist_id": "d0f5f074-740d-4e55-978b-45fdc4f3d754",
        "year_released": 2024
      },
      "id": "f2bcd0ca-df2a-4f59-8be1-cd28c78bfcc2",
      "links": {},
      "meta": {},
      "type": "album",
      "relationships": {
        "tracks": {
          ///////////----- DATA SHOULD GO HERE -----///////////////////
          "links": {
            "related": "http://localhost:4000/api/albums/f2bcd0ca-df2a-4f59-8be1-cd28c78bfcc2/tracks"
          },
          "meta": {}
        },
        // ...

Runtime

Additional context Add any other context about the problem here.

zachdaniel commented 5 months ago

Thanks for the report! fixed in main.