Argument in many to many filter
I have a 2 resources Client and Data in a many to many relationship through a join resource client_data. The join resource has 2 UUID columns for the clients and data, but it also has a 3rd boolean column
exposed?
.
When reading clients through a read action, I want to provide an arg that says to load only the exposed related Data of a Client or the non exposed or both. So I've set an argument
on the read action, but now how do I access it in the filter
expr on the many to many relationship?Solution:Jump to solution
```elixir
prepare fn query, _ ->
case query.arguments[:visibility] do
:exposed -> Ash.Query.load(query, data: Ash.Query.filter(Data, parent(client_data.exposed?)))
end...
12 Replies
Here's an example of my relationship and read action on my Client resource
The idea is to load all clients that have any exposed data, then in each of those clients to load only the exposed data in their
data
field
The problem is that I don't know how to pass the argument in the action to the ^arg/1
in the many to many filter. The DSL documentation for many_to_many.filter says that I should be able to use ^arg/1
Instead, I get this SQL generated for the cond
Admittedly the argument shown here doesn't make much sense given the name and purpose of the action, but I only put it there to have a default value for my argument to see if that would fix the query but it did not.
And I don't want to hard code the filter in the relationship to always choose exposed data because another action is supposed to provide the visibility
argument
If I can't use the arg in the relationship filter, then I think the only option is to define multiple many to many relationships with the same attributes, but different filters and choose which one to load in different actionsyeah, I don't think you can use arguments in relationship. 🤔
I think you could define 3 many to many relationships that have the appropriate filters. and then based on the argument load one respectively in the read action, maybe in a prepare.
or move the whole logic in the read action, should also be possible.
not sure, just an idea. Only Zach will know know. 📿
I think you can only load them or not in a read action, not limit the ones that are returned
Ideally I'd like to avoid repeating my many to many definitions with only a one line difference if possible 😅
you can have a custom query in load. you could make a case in prepare that does a different query filter on through relationship based on the argument.
field policies could help here instead of handling the filtering with the read actions.
https://hexdocs.pm/ash/policies.html#field-policies
as well as policies in general. for read actions policies will apply a filter and field policies gives you further control if they have access to a record but a subset of fields
There are some options. You can filter using arguments when you load them
But the simplest way is to add more relationships
What would this look like?
I think doing
prepare build(load: [:data])
is already going to select them allWDYM select them all?
Oh, sorry
Solution
something like that
Thanks. I ended up with this at the end
It combines everything discussed so far. An argument to determine which related Data to load based on a value in the join resource without creating additional many to many relationships, and strictly loading specific fields and calculations of the related Data