You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Phoenix框架Ecto中timestamp字段自动填充updated_at与inserted_at的方法

嘿,我来帮你搞定Ecto里自动维护inserted_at和updated_at的问题!你的两种尝试里,第一种其实是官方推荐的正确方向,但第二种写法存在明显问题,我来一步步拆解:

为什么你的第二种写法不生效?

直接给字段设置default: :utc_datetime是错误的——:utc_datetime只是一个表示类型的原子,Ecto不会把它自动转换成当前UTC时间,而且这种写法也没有任何逻辑来在更新时自动刷新updated_at字段,自然达不到预期效果。

正确的实现方式(优先用官方宏)

Ecto内置了timestamps/1宏,这是处理时间戳的最优解,它会自动帮你完成:

  1. 定义inserted_at和updated_at字段
  2. 插入数据时自动填充当前UTC时间到两个字段
  3. 更新数据时自动刷新updated_at为当前时间

你的第一个示例其实是对的,只需要确保配合标准的Ecto操作流程即可:

schema "users" do
  field :newsletter, :boolean, default: false
  # 这一行就足够了,type: :utc_datetime 指定用UTC时间
  timestamps(type: :utc_datetime)
end

# 对应的changeset(如果需要做字段验证/转换)
def changeset(user, attrs) do
  user
  |> cast(attrs, [:newsletter])
  # 这里可以加其他验证逻辑,比如validate_required之类的
end

使用的时候不管是通过changeset插入:

Repo.insert(User.changeset(%User{}, %{newsletter: true}))

还是直接插入结构体:

Repo.insert(%User{newsletter: true})

inserted_at和updated_at都会自动被填充为当前UTC时间。当你调用Repo.update/2更新数据时,updated_at也会自动刷新。

自定义时间戳字段(如果需要)

如果你的表不用inserted_at/updated_at这种默认字段名,也可以通过timestamps/1的参数自定义:

schema "users" do
  field :newsletter, :boolean, default: false
  # 自定义字段名,同时指定时间类型
  timestamps(inserted_at: :created_at, updated_at: :modified_at, type: :utc_datetime)
end

手动实现(不推荐,除非特殊需求)

如果你非要手动定义字段并控制逻辑,可以用changeset钩子来处理:

schema "users" do
  field :newsletter, :boolean, default: false
  field :inserted_at, :utc_datetime
  field :updated_at, :utc_datetime
end

def changeset(user, attrs) do
  user
  |> cast(attrs, [:newsletter])
  |> validate_required([])
  |> maybe_set_inserted_at()
  |> set_updated_at()
end

# 只有插入且inserted_at为空时才设置
defp maybe_set_inserted_at(changeset) do
  if is_nil(get_field(changeset, :inserted_at)) do
    put_change(changeset, :inserted_at, DateTime.utc_now())
  else
    changeset
  end
end

# 每次操作都更新updated_at
defp set_updated_at(changeset) do
  put_change(changeset, :updated_at, DateTime.utc_now())
end

不过这种方式不如timestamps宏简洁,而且无法处理直接通过SQL插入数据的场景(timestamps宏会设置数据库层面的默认值),所以除非有特殊需求,优先用官方宏。


内容的提问来源于stack exchange,提问作者Gotrek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:44:55