AE
Ash Elixir•2y ago
Blibs

How to use fragments and not built-in predicates in Ash.Filter keyword list syntax?

The documentation only shows how to use the Ash.Filter keyword list syntax with built-in predicates, how can I use it with fragments or non-built-in predicates? For example, this filter:
Ash.Query.filter(query, expr(fragment("(? <% ?)", :name, "bla")))
Ash.Query.filter(query, expr(fragment("(? <% ?)", :name, "bla")))
How can I write an equivalent using the keyword list syntax?
3 Replies
ZachDaniel
ZachDaniel•2y ago
For safety reasons, there is no real way to do that To prevent from sql injection and that kind of thing What are you doing that would require that?
Blibs
BlibsOP•2y ago
I have a library called AshQueryBuilder https://hex.pm/packages/ash_query_builder I'm currently trying to get support for "scopes", where a scope will encapsulate a list of filters with and or or operations. What I'm trying to do now is to generate the query based on my scopes and filters, so, for example if I have something like this:
[
%Scope{
operation: :or,
filters: [%EqualFilter{field: :name, value: "bla"}, %EqualFilter{field: :name, value: "ble"}]
},
%LessThanFilter{field: :count, value: 10}
]
[
%Scope{
operation: :or,
filters: [%EqualFilter{field: :name, value: "bla"}, %EqualFilter{field: :name, value: "ble"}]
},
%LessThanFilter{field: :count, value: 10}
]
I want to generate a filter like this (name == "value" or name == "ble") and count < 10. To do thins, I'm using the keyword list syntax to generate the query like this, for example:
[
[or: [[male_content: [equals: "blibs"]], [female_content: [equals: "blibs"]]]],
[updated_at: [lt: ~U[2023-08-27 17:01:41.909592Z]]]
]
[
[or: [[male_content: [equals: "blibs"]], [female_content: [equals: "blibs"]]]],
[updated_at: [lt: ~U[2023-08-27 17:01:41.909592Z]]]
]
The problem is that some of my filters are not the built-in ones, for example, I have a LeftWordSimilarity filter, and before, since I didn't have the concept of scopes, I would just simply send the query to that filter and the filter would add itself to the query with Ash.Query.filter(query, expr(fragment("(? <% ?)", ^make_ref(filter), ^filter.value))). The problem is that I don't know how could I so the same but having contexts, can I somehow "merge" Ash.Filter objects with the keyword list syntax? For example, can something like this work?
[
[or: [%Ash.Filter{}, %Ash.Filter{}]]
]
[
[or: [%Ash.Filter{}, %Ash.Filter{}]]
]
? Oh, I just tested that and it seems that it works fine, for example, this keyword list:
[
or: [
%{female_content: %{equals: "blibs"}},
expr(fragment("(? <% ?)", male_content, "bla"))
],
updated_at: %{lt: ~U[2023-08-27 16:43:08.730641Z]}
]
[
or: [
%{female_content: %{equals: "blibs"}},
expr(fragment("(? <% ?)", male_content, "bla"))
],
updated_at: %{lt: ~U[2023-08-27 16:43:08.730641Z]}
]
Will parse just fine 😄
ZachDaniel
ZachDaniel•2y ago
Yep! As long as you construct the sub expression using the expression macro then you’re good because that means a literal string was used

Did you find this page helpful?