dewetblomerus
I am trying to create a code interface that is powered by a query that will grow and evolve over time.
To just play around with Ash queries I tried to start easy and return all the resources where the attribute word is "red".
This code works:
require Ash.Query
Red.Practice.Card
|> Ash.Query.filter(word == "red")
|> Red.Practice.read!()
But the above is not a nice code interface.
Under actions I have tried to create the following:
read :next do
# filter(is_nil([:retry_at]))
# filter(expr([:retry_at] == "NULL"))
# filter([:word] == "red")
end
None of those worked.
I am clearly guessing here and not finding any examples in the documentation. I was looking here but it does not seem like any of these examples are for using inside of a resource. It looks like it is meant for building queries like I already have working.
Bonus round:
Ultimately I need a next action that filters to actor: user, if there is a resource with a retry_at in the past, return the one with the oldest retry_at date. If not, return a resource with retry_at: nil and the oldest created_at. I don’t need that code written for me, but which documentation or example should I be looking at for composing a query inside of a resource action and exposing it through a code interface.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #performance










First 8 of 8 Posts
zachdaniel
There are a couple elements that you’re going to need for this.
The expressions guide shows examples of the kinds of things you can do with
expr. In your case what you’re looking for isWhat you might end up wanting to do for simplicities sake is writing an action that uses an after_action hook to detect that no results were returned and tries another query (your second condition).
With that said, you may also be able to accomplish this with sorts and calculations. For example, you could have a calculation that returns the
retry_atas long as its in the past or,nilotherwise, something like:I think that combined with a
limitof1would get you what you need.Docs for sort/limit is here: Ash.Query — ash v3.29.3
Docs for calculations here: Calculations — ash v3.29.3
dewetblomerus
Thanks, Zac
. This works to return all the instances of the resource where the attribute is nil:
I’ll report back when I find time to try the rest.
dewetblomerus
I was able to make the
after_actionwork. Here are mycode_interfaceandactionblocks:One problem is that I was unable to figure out how to pass an
actorto a read action. I was also unable to useAsh.get_actor()outside of theprepare fn queryblock, so I just made the code interface to accept auser_idbut this interface would only ever be used by the actor that owns the resources being returned, so I would like for it not to receive auser_idas an argument.zachdaniel
The actor should be available as an option to Ash.Query.for_read, does that not work?
zachdaniel
And then it will be in
context.actor(context is the second argument to the prepare function)dewetblomerus
I tried this. I went down this path for a while for the purposes of learning, but this code lives outside of the resource and I would want the code interface to expose a single function to anything outside of the resource.
The above is valid code and returns a result, but it does not filter by actor automatically.
Which made me think I still need to filter by actor in the filter expression, but I do not know how to access the actor there.
I tried this, which is invalid:
filter expr(retry_at < now() and user_id == ^context.actor)The
preparefunction had anafter_actionwhich ran after we already queried DB results belonging to other users, so it felt too late to start filtering there.I also tried the following to see if I can add the filter in a before_action which was valid code, but the
before_actionnever ran:I am okay with just passing the
user_idas an argument to the code interface. It would be used like this from outside of the resource:Red.Practice.Card.next(user.id).I will probably never create a JSON or GraphQL Api for this app. But I suspect that if I do, I would need to find a way to just use the auth context and not pass in an argument here.
But if @zachdaniel or anyone else is willing to keep helping me find the even-more-better way to do this, I’m open to keep trying things.
zachdaniel
Referencing the actor from a template looks like this:
Your before action hook never ran because you didn’t return the new query containing the before_action hook. It would look something like this:
dewetblomerus
By Golly it works


If anyone else is still following along and wants a complete example, here is the now-beautiful interface that can be used elsewhere in the application:
And here is the resource: