AshJsonApi + Managed Relationships
psychonaugty:
Are there any examples of AshJsonApi, the docs seem outdated. Im trying to get managed relationships to work through a ‘parent’ resource.
psychonaugty:
This is my current setup for a “Location” resource and an “Area” managed relationship:
...Location resouce which has many areas
relationships do
has_many :areas, Area
end
json_api do
type "location"
includes(areas: [])
routes do
base("/locations")
get(:read)
index :read
post(:create)
delete(:destroy)
related(:areas, :read)
relationship(:areas, :read)
post_to_relationship(:areas)
patch_relationship(:areas)
delete_from_relationship(:areas)
end
end
update :update do
argument :areas, :map do
allow_nil? false
end
change manage_relationship(:areas, type: :create)
end
psychonaugty:
When trying to get
http://localhost:4000/api/locations/55b9cd3c-8a83-431e-b580-98365bc2b5ab/relationships/areas
, I get a
500
psychonaugty:
psychonaugty:
This is the
Area
resource
...Area resource
json_api do
type "area"
routes do
base("/areas")
get(:read)
index :read
post(:create, relationship_arguments: [{:id, :location}])
patch(:update, relationship_arguments: [:location])
delete(:destroy)
related :location, :read do
primary? true
route("/:id/location")
end
relationship :location, :read do
primary? true
end
end
end
relationships do
belongs_to :location, Location, allow_nil?: false
end
zachdaniel:
Oh, okay that looks like a bug that may actually have been fixed already
zachdaniel:
are you on the latest version of
ash_json_api
?
zachdaniel:
If so, can you try pointing at main?
github: "ash-project/ash_json_api", ref: "main"
?
psychonaugty:
<@197905764424089601> That works! Although it does not return any of its fields, just an id and type
zachdaniel:
🤔
zachdaniel:
oh, yeah that is correct
zachdaniel:
relationship/2
creates an endpoint designed to do that
zachdaniel:
if you want an endpoint that returns the full related entities thats when you use
related/2
zachdaniel:
which is typically the difference between
/thing/:id/relationships/related
and
/thing/:id/related
psychonaugty:
hm, tried
http://localhost:4000/api/locations/55b9cd3c-8a83-431e-b580-98365bc2b5ab/areas
but got a 404?
psychonaugty:
sorry, actually worked!
psychonaugty:
Not getting related links for included relationships though, is that right?

zachdaniel:
looks like a
get_related
route needs to be marked as primary to show up there
defp add_related_link(links, request, %resource{} = record, relationship) do
resource
|> AshJsonApi.Resource.route(%{
relationship: relationship.name,
primary?: true,
action_type: :get_related
})
|> case do
nil ->
links
%{route: route} ->
link =
request
|> with_path_params(%{"id" => AshJsonApi.Resource.encode_primary_key(record)})
|> at_host(route)
Map.put(links, "related", link)
end
end
zachdaniel:
So if you set the
get_related
to
primary? true
then it should appear in the links
zachdaniel:
its been a long time since I made that choice, but I imagine it was to solve for cases where there were multiple endpoints to get the same relationship
zachdaniel:
That could probably be improved 🙂
psychonaugty:
That worked too!
psychonaugty:
Im trying to patch a managed resource through the main one, eg:
http://localhost:4000/api/locations/55b9cd3c-8a83-431e-b580-98365bc2b5ab
Curl eg:
PATCH /api/locations/55b9cd3c-8a83-431e-b580-98365bc2b5ab HTTP/1.1
x-api-key: Yc8ccgMNfDcTCDGKWdotZ+1aemcJswQq
x-tenant-id: ef19b3ea-99d8-4fe4-9622-af6931379c6d
Content-Type: application/vnd.api+json
Host: localhost:4000
Connection: close
User-Agent: RapidAPI/4.2.0 (Macintosh; OS X/13.4.1) GCDHTTPRequest
Content-Length: 148
{"data":{"type":"location","relationships":{"areas":{"data":{"type":"area","name":"Train Station X"}}},"id":"55b9cd3c-8a83-431e-b580-98365bc2b5ab"}}
Any idea how that works? I have this on the main resource
get(:read)
index :read
post(:create)
patch(:update)
delete(:destroy)
related :areas, :read do
primary? true
end
relationship(:areas, :read)
post_to_relationship(:areas)
patch_relationship(:areas)
delete_from_relationship(:areas)
zachdaniel:
You provide it as an attribute in that case
zachdaniel:
the map of data to be passed into the managed relationship I mean
zachdaniel:
we pull arguments and attributes out of the
attributes
field (because
JSON:API
doesn’t give us anywhere else to accept input AFAIK)
zachdaniel:
released
0.32.1
so you don’t need to be on a GH branch 🙂
psychonaugty:
Looking at the spec for jsonapi here: https://jsonapi.org/format/#crud-updating-resource-relationships Looks like you can update from passing it as a relationship on patch?
zachdaniel:
actually yeah it looks like we will search for arguments meant to manage relationships
zachdaniel:
ah, thats right, its configured
zachdaniel:
routes do
patch :update, relationship_arguments: [:authors]
end
zachdaniel:
You say which arguments are edited in the relationships