Validation 为什么Changeset.change跳过Elixir中的验证?
这是一个用于插入或更新某些数据的简单函数。 如果用户数据已经在数据库中,我只需更新它,否则我将插入一个包含数据的新行。一切正常,但我对验证有问题。 变更集定义:Validation 为什么Changeset.change跳过Elixir中的验证?,validation,elixir,ecto,changeset,Validation,Elixir,Ecto,Changeset,这是一个用于插入或更新某些数据的简单函数。 如果用户数据已经在数据库中,我只需更新它,否则我将插入一个包含数据的新行。一切正常,但我对验证有问题。 变更集定义: def changeset(struct, params \\ %{}) do struct |> cast(params, [:name, :surname, :user_id]) |> validate_required([:name, :surname, :user_id]) |&g
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :surname, :user_id])
|> validate_required([:name, :surname, :user_id])
|> unique_constraint(:user_id)
end
当前仅在插入期间有效,而在更新期间无效
def add_or_change(user_id, new_data) do
data_from_db = data_by_user_id (user_id)
case data_from_db do
nil ->
Data.changeset(%Data{}, new_data)
|> Repo.insert()
_ ->
Changeset.change(data_from_db, new_data)
|> Repo.update()
end
end
如果尝试将“”作为:name值插入,则会出现预期的错误(不能为空)。但是,如果使用“”as:name值更新现有行,则变更集不会通过验证,并且我的数据库更新不正确。如何在Repo.update()之前在更改时强制验证?根据文档:用于内部数据更改,因此它绕过了验证:
该函数用于处理应用程序内部的数据。因此,既不进行验证也不进行铸造。这意味着change/2
希望更改映射或关键字中的键是原子
您应该使用来应用验证,然后更新验证是否有效。不要使用此选项:
Changeset.change(data_from_db, new_data)
只需运行您已经在使用的相同函数:
Data.changeset(data_from_db, new_data)
顺便说一下,您实际上可以大大简化此函数:
def add_or_change(user_id, new_data) do
(data_by_user_id(user_id) || %Data{})
|> Data.changeset(new_data)
|> Repo.insert_or_update()
end