为什么 Changeset.change 在 Elixir 中跳过验证?
Why Changeset.change is skipping validation in Elixir?
这是一个用于插入或更新一些数据的简单函数。
如果用户数据已经在数据库中,我只需更新它,否则我会插入一个包含数据的新行。一切正常,但我在验证时遇到问题。
变更集定义:
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :surname, :user_id])
|> validate_required([:name, :surname, :user_id])
|> unique_constraint(:user_id)
end
validate_required 目前仅在插入期间有效,在更新期间无效。
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 值插入,我会按预期收到错误消息(不能为空)。但是,如果我使用“”更新现有行作为 :name 值,变更集不会通过验证并且我的数据库更新不正确。如何在 Repo.update() 之前强制对更改进行验证??
根据文档:Ecto.Changeset/2
用于内部数据更改,因此它绕过了验证:
The function is meant for working with data internal to the application. Because of that neither validation nor casting is performed. This means change/2
expects the keys in the changes map or keyword to be atoms.
您应该使用 Ecto.Changeset.cast/4
来应用验证,如果有效则更新。
不要使用这个:
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
这是一个用于插入或更新一些数据的简单函数。 如果用户数据已经在数据库中,我只需更新它,否则我会插入一个包含数据的新行。一切正常,但我在验证时遇到问题。 变更集定义:
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :surname, :user_id])
|> validate_required([:name, :surname, :user_id])
|> unique_constraint(:user_id)
end
validate_required 目前仅在插入期间有效,在更新期间无效。
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 值插入,我会按预期收到错误消息(不能为空)。但是,如果我使用“”更新现有行作为 :name 值,变更集不会通过验证并且我的数据库更新不正确。如何在 Repo.update() 之前强制对更改进行验证??
根据文档:Ecto.Changeset/2
用于内部数据更改,因此它绕过了验证:
The function is meant for working with data internal to the application. Because of that neither validation nor casting is performed. This means
change/2
expects the keys in the changes map or keyword to be atoms.
您应该使用 Ecto.Changeset.cast/4
来应用验证,如果有效则更新。
不要使用这个:
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