moxley
How to apply filtering on a relationship based on the read action of the parent
How do I apply a specific filtering on a related resource that’s two layers down from the parent resource, where the filter is determined from the parent’s read action being called?
Here’s the AshGraphql query:
query GetMember($id: ID!) {
getMember(id: $id) {
id
profile {
answers {
id
visible
}
}
}
}
The Ash resources involved:
- Member
- → has_one Profile
- → has_many Answers
- → has_one Profile
For this particular GraphQL query, the answers should be filtered by visible=true, where visible is an attribute of Answer. The filtering should only apply to this particular action (:get_member), not any other actions.
Most Liked
zachdaniel
Generally speaking this kind of thing is kind of difficult to do. It also causes problems for generic tooling that might think it can do things like cache any given profile that it sees in a gql response.
You could accomplish it with a relatively complex munging of the load statement in a before action hook on the action in question, which if you do go this route I can help you accomplish. You have to account for the fact that loading relationships for ash_graphql sometimes uses a calculation so that it can load the same relationship multiple ways.
We could also potentially add some kind of dedicated tool for preprocessing included relationships based on the action.
With all that said, I’d be very curious to know why you want this and if there are any other alternatives that might work for you. Resolving instances of a given type differently depending on their location in the tree is IMO an anti pattern that can cause problems later down the line.
FlyingNoodle
Is there no way to rewrite the query like this?
query GetMember($id: ID!, $visible: Boolean!) {
getMember(id: $id) {
id
profile(visible: $visible) {
answers {
id
visible
}
}
}
}
In that case, I assume $visible could be used as an argument somewhere? I have never used Ash with Graqphl and I’m quite new to Ash but I have the feeling that it might be easier to implement?
zachdaniel
You can definitely do it out of the box, i.e something like this:
query GetMember($id: ID!) {
getMember(id: $id) {
id
profile(filter: {visible: {eq: true}}) {
answers {
id
visible
}
}
}
}
With that said, I think that @moxley’s use case is actually quite interesting. Masquerading ought to be, I think, its own concept. I might suggest setting up an actual masquerading concept. For instance, you could add a masquerading_user calculation to your user resource that returns nil, and populate that field in a plug using a header. That header would tell your system to do something like "if the user is allowed to masquerade as the user they are requesting to masquerade as, then set the actor to %{that_user | masquerading_user: the_admin}.
Then the relevant user’s policies will automatically apply for that request.
Popular in Questions
Other popular 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
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









