Using struct data in filter expressions

I think I've tried to do this a few times and have never gotten it to work properly. I have a calculation that takes a struct as an argument, and I want to use data from that struct in the expression, eg.
calculate :valid_for_npc_and_topic,
:boolean,
expr(
topic_id == ^arg(:topic) &&
(is_nil(speaker_faction_id) || speaker_faction_id == ^get_path(arg(:npc), :faction_id))
) do
argument :topic, :string, allow_nil?: false
argument :npc, :struct, allow_nil?: false, constraints: [instance_of: Resdayn.Codex.World.NPC]
end
calculate :valid_for_npc_and_topic,
:boolean,
expr(
topic_id == ^arg(:topic) &&
(is_nil(speaker_faction_id) || speaker_faction_id == ^get_path(arg(:npc), :faction_id))
) do
argument :topic, :string, allow_nil?: false
argument :npc, :struct, allow_nil?: false, constraints: [instance_of: Resdayn.Codex.World.NPC]
end
This doesn't error, but generates SQL like ash_elixir_or((d0."speaker_faction_id"::text IS NULL)::boolean, (d0."speaker_faction_id"::text::text = NULL::text)::boolean)::boolean)::boolean) (so the second part isn't working properly). It's probably something simple but I've tried lots of things like ^arg(:npc)[:id], ^ref([arg(:npc)], :id), and nothing else will even compile
Solution:
instead of ^get_path(arg(:npc), :faction_id) it should be get_path(^arg(:npc), :faction_id)
Jump to solution
8 Replies
sevenseacat
sevenseacatOP4mo ago
found this thread https://elixirforum.com/t/read-action-by-related-struct/61955/5?u=sevenseacat but expr(topic_id == ^arg(:topic) && (is_nil(speaker_faction_id) || speaker_faction_id == (^arg(:npc))[:faction_id])) doesn't work either - gives an error:
iex(48)> Ash.Query.for_read(Resdayn.Codex.Dialogue.Response, :for_npc, %{npc: habasi, topic: "bad people"}) |> Ash.read!()
** (Ash.Error.Unknown)
Bread Crumbs:
> Exception raised in: Resdayn.Codex.Dialogue.Response.for_npc

Unknown Error

* ** (RuntimeError) Unsupported expression in Elixir.AshPostgres.SqlImplementation query: %{extra: %{}, name: :get_path, arguments: [%{<all of the NPC stuff>}, [:faction_id]], __struct__: Ash.Query.Function.GetPath, embedded?: false, __predicate__?: false, __function__?: true}
(ash_sql 0.2.76) lib/expr.ex:2392: AshSql.Expr.default_dynamic_expr/6
(ash_sql 0.2.76) lib/expr.ex:3241: AshSql.Expr.maybe_type_expr/6
...
iex(48)> Ash.Query.for_read(Resdayn.Codex.Dialogue.Response, :for_npc, %{npc: habasi, topic: "bad people"}) |> Ash.read!()
** (Ash.Error.Unknown)
Bread Crumbs:
> Exception raised in: Resdayn.Codex.Dialogue.Response.for_npc

Unknown Error

* ** (RuntimeError) Unsupported expression in Elixir.AshPostgres.SqlImplementation query: %{extra: %{}, name: :get_path, arguments: [%{<all of the NPC stuff>}, [:faction_id]], __struct__: Ash.Query.Function.GetPath, embedded?: false, __predicate__?: false, __function__?: true}
(ash_sql 0.2.76) lib/expr.ex:2392: AshSql.Expr.default_dynamic_expr/6
(ash_sql 0.2.76) lib/expr.ex:3241: AshSql.Expr.maybe_type_expr/6
...
with the calculation being used in an action like:
read :for_npc do
argument :npc, :struct,
allow_nil?: false,
constraints: [instance_of: Resdayn.Codex.World.NPC]

argument :topic, :string, allow_nil?: false

filter expr(valid_for_npc_and_topic(npc: ^arg(:npc), topic: ^arg(:topic)))
end
read :for_npc do
argument :npc, :struct,
allow_nil?: false,
constraints: [instance_of: Resdayn.Codex.World.NPC]

argument :topic, :string, allow_nil?: false

filter expr(valid_for_npc_and_topic(npc: ^arg(:npc), topic: ^arg(:topic)))
end
ZachDaniel
ZachDaniel4mo ago
We should make it simpler. But IIRC (^arg(:arg))[:foo] should work But if not we can make it work and/or fix the get_path version for example Maybe you could reproduce in a test in ash core?
sevenseacat
sevenseacatOP4mo ago
so its supposed to work? right. more investigation and/or a failing test
ZachDaniel
ZachDaniel4mo ago
There is supposed to at least be some way to do it yes
sevenseacat
sevenseacatOP4mo ago
ahhhh I had the pin in the wrong place
ZachDaniel
ZachDaniel4mo ago
But ^arg(:foo)[:path] doesn't work because of how pin operators work
Solution
sevenseacat
sevenseacat4mo ago
instead of ^get_path(arg(:npc), :faction_id) it should be get_path(^arg(:npc), :faction_id)
sevenseacat
sevenseacatOP4mo ago
(was looking through the tests for get_path in ash core)

Did you find this page helpful?