Hi!
Stright to the line :
I would like to parse incoming search request in a number subsequential parsing passes like:
defp gen_query(sq) do
from(d in SomeModel, order_by: d.date, distinct: true)
|> gen_query(sq)
end
defp gen_query(dbq, %{ "in_annotations" => true, "str" => str} = sq) do
dbq
|> or_where([q], fragment("lower(?) like lower(?)", q.annotation, ^"%#{str}%"))
|> gen_query(stripe_sq(sq))
end
defp gen_query(dbq, %{ "in_names" => true, "str" => str} = sq) do
dbq
|> or_where([q], fragment("lower(?) like lower(?)", q.name, ^"%#{str}%"))
|> gen_query(stripe_sq(sq))
end
I’m going to leave behind the scope stripe_sq function because it’s pretty trivial and just stripe used keys from map.
And everything is great till we use only one model. But I need to use multiple models with joins (via the first and only first model - SomeModel in my example). And the problem is that I need not only join another table but also use it fields with where or or_where. I don’t actually select it or something - it just for searching proposes.
So the next bodies of the gen_query will be like
defp gen_query(dbq, %{ "in_customers" => true, "str" => str} = sq) do
dbq
|> join(:left, [q], c in assoc(c, :customer))
|> or_where([q, c], fragment("lower(?) like lower(?)", c.full_name, ^"%#{str}%"))
|> gen_query(stripe_sq(sq))
end
defp gen_query(dbq, %{ "in_contractors" => true, "str" => str} = sq) do
dbq
|> join(:left, [q], c in assoc(c, :contractor))
|> or_where([q, c], fragment("lower(?) like lower(?)", c.full_name, ^"%#{str}%"))
|> gen_query(stripe_sq(sq))
end
This scheme also works pretty well while I have only one join ( [q, c] binding ). But there could be a lot of joins and it’s impossible to know how many in advance. The last join appears in the binding at the last position, but I don’t know how to get the last one without listing it all (which is impossible because I don’t know how many joins were there before.
So the question is: is it possible to bind models for where clause by name or take the last element of the binding list?
Thanks a lot!