Ash manual read actions with params

Hello,

I have created a manual read action to check if there is a booking at a certain point in time.

This is the action:

    read :booking_overlaps? do
      argument :datetime, :naive_datetime do
        description "The naive datetime to check for overlaps"
        allow_nil? false
      end

      argument :duration, :integer do
        description "The duration of the period"
        allow_nil? false
      end

      argument :slot_id, :uuid do
        description "The slot to check for overlaps"
        allow_nil? false
      end

      manual CELP.Bookings.ManualActions.FindBookingOverlap
    end

And this is the FindBookingOverlap manual action:

defmodule CELP.Bookings.ManualActions.FindBookingOverlap do
  use Ash.Resource.ManualRead
  require Ash.Query

  def read(ash_query, ecto_query, _opts, _context) do
      q =
      ash_query
      |> IO.inspect(label: "Ash Query")

    # |> Ash.read!()
    # |> IO.inspect(label: "Ash Query Read")

    # To be changed when this works
    {:error, "TODO"}
  end
end

I see in the query the arguments:

Ash Query: #Ash.Query<
  resource: CELP.Bookings.Booking,
  arguments: %{
    duration: 80,
    datetime: ~N[2025-01-28 10:30:00],
    slot_id: "7077cd53-b39f-4604-852b-3f175dab77e9"
  },
   ...
>

My question is, how can I filter using those arguments? These are some things I have tried:

  • Ash.Query.filter(ash_query, slot_id == ^arg(:slot_id))
  • Ash.Query.filter(ash_query, slot_id == :slot_id)

I get an error with the first option, and I think the second option is not correct.

Also, I have another error. When I try to read the results, I get into a recursion loop. That’s why the following code is commented:

    # |> Ash.read!()
    # |> IO.inspect(label: "Ash Query Read")

I also tried to pass the args using the opts variable, but it didn’t work, and I later found that the arguments were already in the query.

How could I use the arguments available in the query?
Why do I get into a recursion loop?

I wonder if I have to modify the query, but I’d like to learn to do it using the manual read action.

You probably don’t need a manual read action to do what you’re trying to do. I’d suggest looking into preparations & filtering there. Preparations — ash v3.4.60

As for the recursion loop, in a manual read, you can’t run the query given to you directly, because it is set to use the action you are currently defining. The idea is that you’d take the things from the query that you support and run perhaps a different action, or an Ecto query for example.

1 Like

Quick question @zachdaniel ,

I have set ‘get? true’ in the action, I want the action to return true or false.

I think I can’t use ‘exists’ on the preparation, because is not a built-in function for ‘Ash.Query’.

Is it possible to return a boolean for the action o actions always expert to return a resource?

Thanks!

Read actions always return records. Look into Generic Actions — ash v3.4.60

1 Like