编辑:我已将此答案更新为EXTO v2.0.你可以在最后阅读上一个答案.
埃克托v2
从最初的答案开始,在Exto中处理UUID变得更加直截了当.Exto有两种ID::id
和:binary_id
.第一个是我们从数据库中知道的整数ID,第二个是特定于数据库的二进制文件.对于博士后来说,这是一个UUID.
要将UUID作为主键,请首先在迁移中指定它们:
create table(:posts, primary_key: false) do
add :id, :binary_id, primary_key: true
end
然后在模型模块中(schema
块之外):
@primary_key {:id, :binary_id, autogenerate: true}
当您为:binary_id
指定:autogenerate
选项时,EXTO将保证适配器或数据库将为您生成它.但是,如果愿意,您仍然可以手动生成它.顺便说一句,您可以在迁移中使用:uuid
,在模式中使用Ecto.UUID
,而不是:binary_id
,:binary_id
的好处是它可以跨数据库移植.
外胚层v1
您需要告诉数据库如何自动生成UUID.或者您需要从应用程序端生成一个.这取决于你喜欢哪一个.
在我们继续之前,有一点很重要,那就是您使用的:uuid
将返回二进制文件,而不是人类可读的UUID.您很可能希望使用Ecto.UUID
,它将把它格式化为字符串(aaaa bbb ccc-…)这就是我下面要用到的.
在数据库中生成
在迁移中,为字段定义默认值:
add :id, :uuid, primary_key: true, default: fragment("uuid_generate_v4()")
我假设你正在运行PostgreSQL.您需要在pgAdmin中安装uuid ossp扩展,或者在迁移中添加execute "CREATE EXTENSION \"uuid-ossp\""
.更多关于the UUID generator can be found here的信息.
回到EXTO,在您的模型中,要求EXTO在插入/更新后从数据库中读取字段:
@primary_key {:id, Ecto.UUID, read_after_writes: true}
现在,当您插入时,数据库将生成一个默认值,并且Ecto将读回该值.
在应用程序中生成
您需要定义一个模块,为您插入UUID:
defmodule MyApp.UUID do
def put_uuid(changeset) do
Ecto.Changeset.put_change(changeset, :id, Ecto.UUID.generate())
end
end
并将其用作回调:
def model do
quote do
use Ecto.Model
@primary_key {:id, Ecto.UUID, []}
@foreign_key_type Ecto.UUID
before_insert MyApp.UUID, :put_uuid, []
end
end
before_insert
是一个回调函数,它将使用给定的参数在给定的函数中调用给定的模块,并将一个表示插入内容的变更集作为第一个参数.
就这些了.顺便说一句,future 这项工作可能会更加精简.:)