I want to be able to call a function or my predicated in "where" of Ecto. I'm trying this:
items = where(Item, [x], Item.my_predicate?(x))
# items = where(Item, [x], Item.my_predicate?(x) == true)
It throws an exception:
`Item.my_predicate?(x)` is not a valid query expression
How to fix it?
Of course it is possible however you cannot use functions but macros.
Example:
defmodule Foo do
defmacro concat_ws(joiner, columns) do
params_list = "?" |> List.duplicate(Enum.count(columns)) |> Enum.join(",")
quote do
fragment(unquote("concat_ws(?," <> params_list <>" )", joiner, unquote_splicing(columns))
end
end
end
items = where(Item, [x], Foo.concat_ws(" ", [x.a, x.b]) == "a b")
Example without fragment
:
defmodule Foo do
defmacro eql(a, b) do
quote do: not (is_nil(a) or is_nil(b)) and a == b
end
end
But still macro result need to be valid query AST, so nothing fancy can land there.