如何在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
相关产品推荐
相关产品推荐

