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

如何在Ecto Changeset中阻止写入nil值?

问题

我有一个update_changeset,希望阻止写入nil值。尝试添加了validate_change验证:

def update_changeset(user, attrs) do
    user
    |> cast(attrs, [:full_name])
    |> validate_change(:full_name, fn :full_name, full_name ->
      if full_name == nil do
        [full_name: "cannot be blank"]
      else
        []
      end
    end)
  end

但该验证仅在存在非nil值时才会被调用,因此仍然允许将full_name: nil写入数据库。请问如何解决这个问题?

原因

validate_change的触发条件是字段存在于变更集中(即该字段被修改过),如果传入的attrs中没有full_name字段,或者明确传入full_name: nil但该值和原记录值一致时,这个验证不会执行,导致nil值依然能写入。

解决方案

可以自定义一个验证函数,直接检查字段的当前值(不管是否被修改),如果是nil或空字符串就添加错误。比如你已经实现的这个辅助函数:

defp prevent_empty(changeset, fields) do
    Enum.reduce(fields, changeset, fn field, changeset ->
      value = get_field(changeset, field)

      if value in ["", nil] do
        add_error(changeset, field, "cannot be empty or blank")
      else
        changeset
      end
    end)
  end

在update_changeset中调用这个函数即可:

def update_changeset(user, attrs) do
    user
    |> cast(attrs, [:full_name])
    |> prevent_empty([:full_name])
  end

这样无论字段是否被修改,都会检查其当前值,确保不会写入nil或空字符串。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:45:32