2016-01-26 9 views
9

Lassen Sie uns sagen, ich habe diese Anfrage:Verfassen einer Ecto-Abfrage mit mehreren Spalten in einer where-Klausel verbunden durch OR

User 
|> where([u], u.name == "John" or u.age == 24) 

Ich möchte diese in eine Funktion aktivieren, die eine Keyword-Liste von Feldnamen und Feld nehmen Werte und generieren dynamisch dieselbe Abfrage. Die Funktionsdefinition würde etwa so aussehen:

def where_any(query, field_names_to_values) do 
    ... 
end 

Ist dies mit Elixir und Ecto möglich?

+1

ich diese Art von composability mit Makros in einer Bibliothek von mir tun, wie @jisaacstone schlägt vor, . Ein Beispiel finden Sie unter https://github.com/rcdilorenzo/filtrex/blob/master/test/ast_test.exs. –

Antwort

2

Würde normalerweise kein Makro befürworten, aber Ecto macht so viel komplexe Magie Ich denke, es ist in diesem Fall am besten, den abstrakten Syntaxbaum intakt zu halten.

defmacro any_expr(var, [{key, value} | rest]) do 
    Enum.reduce(
    rest, 
    quote do unquote(var).unquote(key) == unquote(value) end, 
    fn ({k, v}, acc) -> 
     quote do: unquote(acc) or unquote(var).unquote(k) == unquote(v) 
    end) 
end 

soll wie folgt funktionieren:

User 
|> where([u], any_expr(u, [name: "John", age: 24])) 

(beachten Sie, dass diese nicht getesteten Code ...)