基于macro 仿写一个简单的ecto schema dsl
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 很重要