{@thread.name}
Jan Ulbrich:
I have a read action (and JSON API route) that takes an alternative identifer
:extid
instead of looking for the
:id
column. Now I would like the same route as an alternative for updates, too.
The
update
understands the
argument
like the
read
does, but I don’t see how I can modifiy the query to read the correct record.
A
change
can have an optional
where
which takes a list of functions, but I don’t get what these functions should look like…
ZachDaniel:
Like you want to update the record with the given
:extid
?
ZachDaniel:
You would do something like this:
patch :update_action do
route "/:extid"
end
ZachDaniel:
And then it would look up with the
extid
attribute
Jan Ulbrich:
Oh, then I had it right. I got this error message and though I need to fix the lookup:
PATCH /api/eventhub/events/alarms/R202201010001 ** (exit) an exception was raised: ** (RuntimeError) Haven't figured out more complex route parameters yet.
ZachDaniel:
…
ZachDaniel:
what
ZachDaniel:
lemme take a look 😆
ZachDaniel:
oh, wow
ZachDaniel:
thats an error in the json schema building
ZachDaniel:
unless properties == [] or properties == ["id"] do
raise "Haven't figured out more complex route parameters yet."
end
ZachDaniel:
But of course that is being used to validate the input and so is causing a problem
ZachDaniel:
I’ll fix it
Jan Ulbrich:
Wow, you’re amazing! 😄
Jan Ulbrich:
Here’s a more complete part of my code:
json_api do
type "event"
routes do
base("/events")
get(:read_alarm, route: "/alarms/:extid")
get(:read)
patch(:update_alarm, route: "/alarms/:extid")
patch(:update)
end
end
update :update_alarm do
argument :extid, :string, allow_nil?: false
change fn changeset, context ->
patch_changeset_applying_actor_filters(changeset, context)
end
end
update :update do
change fn changeset, context ->
patch_changeset_applying_actor_filters(changeset, context)
end
end
Compiler:
ZachDaniel:
Hey <@1066359540003643526> would you mind trying ash_json_api’s
main
branch?
Jan Ulbrich:
Sure, gimme a couple of minutes…
Jan Ulbrich:
At least I’m getting nearer! 🙂
First I ran into error
"InvalidBody", "detail": "Required properties are missing: [\"extid\"], at [\"data\", \"attributes\"]."
which tells me, that the
extid
isn’t read from the path.
I added it to the body to get further and now I get
FrameworkError", "detail": "Returned when an unexpected error in the framework has occured."
without any exception. In the log I see that a query was executed on the database and the query looks good!
Jan Ulbrich:
Ha, I guess I know the problem: The
extid
is not unique without a second condition which I need to add. Can I add an additional where clause?
ZachDaniel:
You can only have one
filter
on a read action
ZachDaniel:
but you can do things like
filter expr(foo == ^arg(:foo) and bar == ^arg(:bar))
Jan Ulbrich:
In the
read
I already have that
filter
, but an
update
doesn’t offer that… 😇
Jan Ulbrich:
I guessed, that the
where
of the
change
could help me, but I couldn’t figure out how.
Jan Ulbrich:
The
read
looks like this:
read :read_alarm do
argument :extid, :string, allow_nil?: false
filter expr(kind == "ALARM" and subkind == "NEW" and extid == ^arg(:extid))
prepare fn query, context ->
Ash.Query.after_action(query, fn _query, events ->
{:ok, patch_results_applying_actor_filters(events, context)}
end)
end
end
The
update
looks like this (and obviously the additional where clause is missing to make the lookup unique):
update :update_alarm do
argument :extid, :string, allow_nil?: false
change fn changeset, context ->
patch_changeset_applying_actor_filters(changeset, context)
end
end
ZachDaniel:
ah, the
where
of the change is for something else 🙂
ZachDaniel:
That is for conditionally running changes
ZachDaniel:
Can I see your
patch
route with the additional field?
Jan Ulbrich:
Sure, here:
patch(:update_alarm, route: "/alarms/:extid")
The whole rout block is further above…
ZachDaniel:
I think you need the other field in there right?
ZachDaniel:
You mentioned its not unique on
:extid
Jan Ulbrich:
See the read: The lookup per
extid
is unique as long as I have the additional clauses.
ZachDaniel:
Ah, I see
Jan Ulbrich:
Database model isn’t mine, so not the nicest stuff, but legacy I need to live with… 😇
ZachDaniel:
Not a problem 🙂
ZachDaniel:
So this is a feature we have in
ash_graphql
that hasn’t been added to
ash_json_api
yet
ZachDaniel:
It will not be hard to add, but what you basically need to be able to do is customize the read action used to look up the thing you want to update
ZachDaniel:
something like this:
patch "/alarms/:extid" do
read_action :read_alarm
end
ZachDaniel:
Its an easy change, and I will make it later tonight
ZachDaniel:
keeping up with all the extensions can be tough sometimes so features are generally added on an as-needed basis and you’re the first person to ask for this one for ash_json_api, but its a very important feature 🙂
Jan Ulbrich:
You’re brilliant! 🤩 But please don’t go crazy: I can live without that for the moment.
And that I need to put the
extid
in the patch body is related to the same, right?
Jan Ulbrich:
I wanted to look into the Ash GraphQL next anyways… 🙂 Thanks a lot for your help, good night! 😴
ZachDaniel:
Yeah, exactly. The
extid
should be fine to be in the route 😄 once its fixed
ZachDaniel:
Can you try
main
now? Should work the way you want it to 🙂
ZachDaniel:
But you’ll add
read_action : read_alarm
ZachDaniel:
I’ve added it to
patch
and
delete
ZachDaniel:
Will likely need to add it to others as well, but this gets the initial support going
Jan Ulbrich:
Wow, will do!
Jan Ulbrich:
The
read_action
does the trick now! 👏 So I can ship that tomorrow. Will go to sleep now happily… 😄 🙃 😴 Thank you very much! 🤩
ZachDaniel:
🥳 glad I could help!