ash json api don't work with aggregates

I have a resource that has this aggregate:
aggregates do
first :last_bid_price, :bids, :price do
sort inserted_at: :desc
end
end
aggregates do
first :last_bid_price, :bids, :price do
sort inserted_at: :desc
end
end
If I add json api for that resource like this:
json_api do
type "property"

routes do
base "/property"

index :read
end
end
json_api do
type "property"

routes do
base "/property"

index :read
end
end
If I try to get that resource with curl 'localhost:4000/api/markets/property' I will get this error:
[error] #PID<0.811.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.810.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /api/markets/property
** (exit) an exception was raised:
** (MatchError) no match of right hand side value: {:error, "Must provide field type for first"}
(ash_json_api 0.31.1) lib/ash_json_api/json_schema/json_schema.ex:506: anonymous fn/2 in AshJsonApi.JsonSchema.filter_props/1
...
[error] #PID<0.811.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.810.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /api/markets/property
** (exit) an exception was raised:
** (MatchError) no match of right hand side value: {:error, "Must provide field type for first"}
(ash_json_api 0.31.1) lib/ash_json_api/json_schema/json_schema.ex:506: anonymous fn/2 in AshJsonApi.JsonSchema.filter_props/1
...
Which happens in the json_schema.ex:505 file. This is what the agg variable has at the time the error happens:
%Ash.Resource.Aggregate{
name: :last_bid_price,
relationship_path: [:bids],
filter: [],
kind: :first,
implementation: nil,
constraints: nil,
type: nil,
description: nil,
private?: false,
field: :price,
sort: [inserted_at: :desc],
default: nil,
filterable?: true
}
%Ash.Resource.Aggregate{
name: :last_bid_price,
relationship_path: [:bids],
filter: [],
kind: :first,
implementation: nil,
constraints: nil,
type: nil,
description: nil,
private?: false,
field: :price,
sort: [inserted_at: :desc],
default: nil,
filterable?: true
}
Which means that the function is called with: Aggregate.kind_to_type(:first, nil)
16 Replies
ZachDaniel
ZachDaniel3y ago
Thanks for the report! This is definitely a bug, can you log this on the asj_json_api GH repo and I'll address soon?
Blibs
BlibsOP3y ago
GitHub
Ash json api don't work with aggregates · Issue #69 · ash-project/a...
Describe the bug A read action will not work with JSON API if that action uses an aggregate. To Reproduce I have a resource that has this aggregate: aggregates do first :last_bid_price, :bids, :pri...
ZachDaniel
ZachDaniel3y ago
can you give ash_json_api main a shot? LMK if it works I pushed up a quick fix that I'm pretty sure will work 😆
Blibs
BlibsOP3y ago
Seem to be working
ZachDaniel
ZachDaniel3y ago
🥳
Blibs
BlibsOP3y ago
but shouldn't my aggregate also come with the response? I can't see a last_bid_price field in the response
ZachDaniel
ZachDaniel3y ago
We don't include aggregates by default you need to include ?fields=foo,bar,baz and include the fields you want which is a bit annoying, but thats how JSON:API spec works
Blibs
BlibsOP3y ago
Like this? http://localhost:4000/api/markets/property?fields=last_bid_price
ZachDaniel
ZachDaniel3y ago
and we can't reasonably include all fields by default because it might be expensive. actually I think its fields[type]=list so fields[property]=last_bid_price,...all-the-rest We can add an option to let you specify the default fields for a type at some point
Blibs
BlibsOP3y ago
So, if I try this: localhost:4000/api/markets/property?fields[property]=last_bid_price It actually crashes in the server with:
[error] #PID<0.876.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.875.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /api/markets/property?fields[property]=last_bid_price
** (exit) an exception was raised:
** (UndefinedFunctionError) function nil.embedded?/0 is undefined
nil.embedded?()
(ash_json_api 0.31.1) lib/ash_json_api/serializer.ex:595: anonymous fn/4 in AshJsonApi.Serializer.serialize_attributes/2
(elixir 1.14.0) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash_json_api 0.31.1) lib/ash_json_api/serializer.ex:393:
...
[error] #PID<0.876.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.875.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /api/markets/property?fields[property]=last_bid_price
** (exit) an exception was raised:
** (UndefinedFunctionError) function nil.embedded?/0 is undefined
nil.embedded?()
(ash_json_api 0.31.1) lib/ash_json_api/serializer.ex:595: anonymous fn/4 in AshJsonApi.Serializer.serialize_attributes/2
(elixir 1.14.0) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash_json_api 0.31.1) lib/ash_json_api/serializer.ex:393:
...
ZachDaniel
ZachDaniel3y ago
lemme check okay try main again
Blibs
BlibsOP3y ago
Seems to be working now! Kinda a pain that I will need to specify all the rest of the fields in this case, but it is part of the specification nothing related to ash
ZachDaniel
ZachDaniel3y ago
Yeah, agreed. We can potentially add our own logic to it, like add our own add_fields[type] that will keep the default but that would just be in addition to the spec compliant behavior
Blibs
BlibsOP3y ago
A little bit off-topic, but in your opinion do you think the GraphQL library for Ash is more mature than the jsonAPI one?
ZachDaniel
ZachDaniel3y ago
significantly 🙂 Not because I think JSON:API is a worse choice there are just a lot more people using ash_graphql
Blibs
BlibsOP3y ago
I will try that out then. Either way thanks a lot for the fix 😁

Did you find this page helpful?