Why don't read actions filter by attributes?

rgraff
2023-08-03

rgraff:

Given a read action

code_interface do
  define :read
end

actions do
  defaults [:read]
end

There are no arguments for the action, so the following does not select on email .

iex(21)> Membership.read(%{email: "tom@example.com"}, authorize?: false)
[debug] QUERY OK source="memberships" db=0.6ms queue=0.1ms idle=1341.0ms
SELECT m0."id", m0."role", m0."email", m0."invitation_token", m0."invited_at", m0."inserted_at", m0."updated_at", m0."organization_id", m0."user_id" FROM "memberships" AS m0 []

I would assume any filterable attributes would be automatically applied as a filter. You could also have an accepts option on the action to limit it certain filterable attributes.

barnabasj:

https://ash-hq.org/docs/guides/ash/latest/code-interface#using-the-code-interface

you can use a query for filtering

e.g. Membership.read(authorize?: false, query: MemberShip |> Ash.Query.new() |> Ash.Query.filter(email: "tom@example.com"))

zachdaniel:

Yep! And if you want to parse a filter from input (like query params), you’d use Ash.Filter.parse_input!

zachdaniel:

That would prevent any funny business, only allowing basic attribute references to public attributes

zachdaniel:

(and not functions, for example)

rgraff:

This is a question more about the philosophy and intent, and less asking “how to?”.

Yes, we’re currently using Ash.Query to filter. My question was “why?” because it seems like such a common use case. I think of using query as an escape hatch of sorts, because I really want my actions to define the intended usecases.

It’s similar to how the GraphQL interface creates the input automatically from what’s filterable. You don’t have to define a read action with arguments for the filterable attributes.

zachdaniel:

Yes, but it does that by using the same feature just laid out, the fact that any given read action can be given a narrowing query

zachdaniel:

And as such ash_graphql supports things like {or: [{...}, {...}]} as opposed to just a key/value of attributes to filter on

zachdaniel:

Its not an escape hatch, its a design benefit of read actions

zachdaniel:

You can support explicit arguments with filters, like:

read :read do
  argument :foo, :string
  argument :bar, :string
  prepare fn query, _ -> 
    YourHelpers.filter_on_provided_arguments(query, [:foo, :bar])
  end
end

zachdaniel:

Or you could even write an extension that would add those arguments to all read actions (although I probably wouldn’t)

rgraff:

I see. It’s more about being more robust than a simple key/value filter.

Thanks for helping me understand

zachdaniel:

👍 any time!