是的,这是可能的Module.create/3
。有一些注意事项:您需要为每个模块选择一个唯一的名称,并且模块的代码将驻留在内存中,直到 VM 重新启动,因此您可能需要限制调用此函数的次数。
这是您可以构建的基本实现。它允许您传递模块名称、表名称以及字段名称和类型对的列表。
defmodule A do
def go(module, table, fields) do
Module.create(module, quote do
use MyApp.Web, :model
schema unquote(table) do
unquote(for {name, type} <- fields do
quote do
field unquote(name), unquote(type)
end
end)
end
end, Macro.Env.location(__ENV__))
end
end
A.go MyPost, "posts", [
{:title, :string},
{:content, :string},
]
# MyPost is now just like any other Schema module in Phoenix.
IO.inspect MyApp.Repo.all(MyPost)
Output:
[debug] QUERY OK source="posts" db=2.8ms queue=0.1ms
SELECT p0."id", p0."title", p0."content" FROM "posts" AS p0 []
[%MyPost{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">,
content: "Hello from Joe", id: 1, title: "Hello"},
%MyPost{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">,
content: "Hello from Mike", id: 2, title: "Hello"},
%MyPost{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">,
content: "Hello from Robert", id: 3, title: "Hello"}]