2017-10-04 19 views
0

Ectoの "where"にある関数または私の述語を呼び出せます。私はこれをしようとしている:Ectoの "where"で自分自身の述語を呼び出す

items = where(Item, [x], Item.my_predicate?(x)) 

# items = where(Item, [x], Item.my_predicate?(x) == true) 

それが例外をスローします。

`Item.my_predicate?(x)` is not a valid query expression 

それを修正する方法は?

+0

これはできません。このようなクエリがある場合、データベースのクエリ言語に変換する必要があります。その内部に任意のコードを書き始めると、ectoはその翻訳を行うことができません。 –

+0

実行したい述語と使用するDBのサンプルを提供する場合は、より多くのヘルプを提供する方が簡単です。 – Hauleth

答えて

0

もちろん、関数but macrosを使用することはできません。

例:fragmentなし

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") 

例:何も空想が着陸することができますので

defmodule Foo do 
    defmacro eql(a, b) do 
    quote do: not (is_nil(a) or is_nil(b)) and a == b 
    end 
end 

しかし、まだマクロの結果は、有効なクエリのASTにする必要があります。

+0

なぜマクロですか?フラグメントを必要としない自分自身の述語をどのように使用できますか? – Bingi

+0

@Bingiでも、 'where'は必須のASTを持つ' Ecto.Query'構造を構築するマクロであるとしてマクロを使う必要があります。 Ectoにその関数コードをDBクエリに変換させる必要があるので、カラムデータの関数を呼び出す方法はありません。 Ectoクエリのすべては事前計算され、生データとしてDBに送信するか、クエリに変換可能にする必要があります。 'fragment'を使う必要はありませんが、一般的にはEctoマクロが必要な場合です。ただし、クエリに使用できるコードを自由に書くことができます。それ以外の場合は不可能です。 – Hauleth

+0

フラグメントを必要としない独自の述語を使用するにはどうすればよいですか? – Bingi

0

私は考えられません。それはどこへ行くただ一つの方法です明らかに

defmodule CheapItemPolicy do 
    alias Ecto.Query 
    import Query, only: [where: 3] 

    def is_cheap?(%Item{price: price}) do 
    price in 100..200 
    end 

    def is_cheap?(%Query{} = query) do 
    query 
    |> where([q], q.price >= 100) 
    |> where([q], q.price <= 200) 
    end 
end 

行くための一つの方法として、あなたは、レコードやクエリの一部としてそれを処理する機能を実装して別のポリシーモジュールを作成することができます。これらの関数をすべて既存のモジュールに入れたり、別のモジュールに分割したり、同じロジックを持つデータベース関数を作成したり、アプリケーションレベルのチェックなどを処理することができます。

0

ルーカスの答えが必要です。 Ectoクエリはコンパイル時に構築されるため、何かを述語として使用する場合はマクロが必要です。

しかし、クエリを作成することもできます。

def my_predicate(query, value) do 
    from r in query, where: r.some_column == ^value 
end 

など、それを使用します:基本的に

query = from r in MySchema, where: r.another_column == ^another_value 

query |> my_predicate(some_value) 

、構成可能な機能を使って、少しして、クエリのビットを構築するこれはあなたのアイデアを与える必要があります。

PS。私は常にEctoクエリーのために "クエリー"フォームを使用します。また、 "piped"フォームを使用して、クエリを関数にパイプすることでクエリを構成することもできます。

+0

私に必要なものを教えてください、あなたなしではわかりません。 – Bingi

+0

申し訳ありませんが、私はあなたが意味するものを取得していません。より具体的な例が必要ですか? – vfsoraki

関連する問題