Search code examples
macroselixirmetaprogrammingecto

Call a custom Macro in an Ecto Schema block


Schema module definition for the Ecto framework:

defmodule Storage.Repo.Category do
  use Ecto.Schema

  schema "categories" do
    field :name
    field :path
    field :color
    field :desc
    field :sequ, :integer

    hello()
    timestamps()
  end

  defmacro hello do
    quote do
      field :hello
    end
  end
end

Compile failed

 (CompileError) lib/storage/repo/category.ex:15: undefined function hello/0

What should I do? What is the cause of this?


Solution

  • You need to define your Macro in an other module, require/import it and then call it:

    defmodule Storage.SchemaMacros do
      defmacro hello do
        quote do
          field :hello
        end
      end
    end
    

    Now call it:

    defmodule Storage.Repo.Category do
      use Ecto.Schema
      import Storage.SchemaMacros
    
      schema "categories" do
        field :name
        field :path
        field :color
        field :desc
        field :sequ, :integer
    
        hello()
        timestamps()
      end
    end
    

    You can usually define and call macros in the same module (as long as it's defined before calling it), but the way Ecto's own schema/2 macro works under the hood does not allow you to do that.