albertored
Ex_sieve - Filtering solution for Ecto, it builds Ecto.Query structs from a ransack inspired query language
ex_sieve is a library offering a filtering solution for Ecto. It builds Ecto.Query structs from a ransack inspired query language.
It was originally developed by @valyukov, a few months ago I joined the project and started extending his great work. I have just released version 0.8.0, it includes a lot of new features and improvements, you can take a look at the changelog and at the documentation.
Any feedback is welcome!
Most Liked
Eiji
Not sure if this code is best, but at least it does not depend on private API:
defp do_apply_join({parent, relation} = parent_relation, query)
when is_atom(relation) and (is_binary(parent) or is_nil(parent)) and
(is_atom(query) or :erlang.map_get(:__struct__, query) == Ecto.Query) do
as = join_as(parent_relation)
query |> Macro.escape() |> join_build(parent_relation, as) |> elem(0)
end
defp join_build(query, {nil, relation}, as) do
Code.eval_quoted(
quote do
join(unquote(query), :inner, [p], a in assoc(p, unquote(relation)), as: unquote(as))
end
)
end
defp join_build(query, {string, relation}, as) do
parent = String.to_atom(string)
Code.eval_quoted(
quote do
join(unquote(query), :inner, [{unquote(parent), p}], a in assoc(p, unquote(relation)), as: unquote(as))
end
)
end
Notes:
- Since we are using
evalhere I have added some guards. To make sure nothing would explode you may add extra runtime checks (regex?) forparentandrelationcontents. - Make sure to add
import Ecto.Queryand remove unusedalias Ecto.Query.Builder.Joinandjoin_binding/1private function.
dalerka
Ex_sieve seems very powerful, yet there’s also a simpler library - Flop - also in early dev stage. Kudos to authors and contributors!
Can someone well-versed in Ecto comment about the benefits and downsides in regard to how both libraries approach DB querying, eg. security, performance, query-composing and general dev experience?
albertored
The documentation contains some example.
The main use case is to create a filter query on a list view taking as input user supplied URL query parameters. But this is not the only possible use, the Repo.filter function provided by the library takes as input a map that can be built in many different ways.
LostKobrakai
I’m wondering why you didn’t implement Ecto.Queryable for a struct holding the filter input. then this would be usable with all Repo functions and not just your custom injected Misunderstood filter/2.Repo.filter, which does return a query.
albertored
Yes, maybe the API it’s not the better one but I didn’t consider changing the original one before releasing 1.0.0. Your suggestion it’s indeed good, I will investigate on it, thanks!
Also for release 1.0 I would like to remove the remaining usage of Ecto internal APIs. In particular I didn’t find a way of building dynamic joins without relying on Ecto.Query.Builder.Join.join/10.







