基于macro 仿写一个简单的ecto schema dsl

发布时间 2024-01-05 13:52:19作者: 荣锋亮

ecto 的schema macro 是一个很方便的功能,可以用来定义表的schema 信息,以下是一个简单的仿写(只是行像,但是功能不一样)

项目代码

  • macro 定义
    e.ex
 
defmodule E do
   # 方便use 使用
  defmacro __using__(_options) do
    quote do
      import E
      # 通过属性存储信息
      Module.register_attribute(__MODULE__, :fields, accumulate: true)
    end
  end
  # schema macro 定义,与ecto 的类型,一个是schema 名称,一个是里边的代码定义(schema 的字段信息)
  defmacro schema(name,do: block) do
     # 调用一个内部的私有方法,返回macro,macro 方法然后使用
     schema(name,:dalong,block)
  end
  # filed macro, 进行schema 字段配置
  defmacro filed(name,type) do
    quote do
      name = unquote(name)
      type = unquote(type)
      # 存储到模块的属性中
      Module.put_attribute(__MODULE__, :fields, {name,type})
      # 为了方便测试,输出
      IO.inspect(Module.get_attribute(__MODULE__, :fields))
    end
  end
 
  defp schema(name,source,block) do
    quote  do
      source = unquote(source)
      name = unquote(name)
      # 类型ecto name 必须是一个binary  (string)
      unless is_binary(name) do
        raise "name must be a string"
      end
      IO.puts("source: #{source} name: #{name}")
      unquote(block)
   end
  end
end
  • 使用
    f.ex 与ecto 的基本类似
 
defmodule F do
  use E
  schema "dalong" do
    filed :name, :string
    filed :age, :ineteger
    filed :version, :string
  end
end
  • 测试效果
iex -S mix

说明

elixir 的元编程在不少框架中都有频繁的使用,学习好macro 很重要

参考资料

https://hexdocs.pm/ecto/Ecto.html#module-schema