2017-02-16 5 views
0

機能をスキーマに追加するには?モデルスキーマにフィールドを動的に追加するための関数を作成したいと思います。例:あなたは、このモジュールの身体からそれを呼び出すようにしたいので、Phoenix、モデルスキーマ

def func do 
    # .. loop to create dynamic fields 
    field :street, :string 
    end 

    schema "objects" do 
    func 
    end 

... Error: 

** (CompileError) web/models/objects.ex:12: undefined function func/0 

答えて

5

funcは別のモジュールにする必要があります。 funcfieldコールを含む引用されたASTを返すマクロである必要があります。fieldfieldもマクロなので、正しいモジュールにフィールドを入れることができます。あなたはこのような何かを探している:

defmodule MyApp.Post.Helper do 
    defmacro func do 
    quote do 
     field :foo, :string 
    end 
    end 
end 

defmodule MyApp.Post do 
    use MyApp.Web, :model 
    import MyApp.Post.Helper 

    schema "posts" do 
    func() 
    end 
end 

テスト:

iex(1)> %Post{} 
%MyApp.Post{__meta__: #Ecto.Schema.Metadata<:built, "posts">, foo: nil, id: nil} 
+0

私はFUNCをDEFMACROするためのパラメータを渡すことができますか..? –

+2

はい、機能パラメータとまったく同じではありません。引用符/引用符を使用する必要があります。 http://elixir-lang.org/getting-started/meta/macros.htmlを参照してください。 – Dogbert

+0

_Sidenote:_ 'defmacro'は関数ではなく、[マクロ自体](https://github.com/elixir-lang/elixir/blob/edd38eee485789f88836866094f852a8f5e2ebfb/lib/elixir/lib/kernel.ex#L3462)です。 – mudasobwa