这是一个用于插入或更新某些数据的简单函数。 如果用户数据已经在db中,我只需更新它,否则我插入一个包含数据的新行。一切正常,但我有验证问题。 变更集定义:
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
如果我尝试插入"" as:name value,我得到一个错误(不能为空)。但是,如果我用""更新现有行? as:name值,changeset不通过验证,我的db更新不正确。如何在Repo.update()??
之前强制进行更改验证答案 0 :(得分:1)
根据文档:Ecto.Changeset/2
用于内部数据更改,因此它会绕过验证:
该函数用于处理应用程序内部的数据。因此,既不执行验证也不执行铸造。这意味着
change/2
期望更改映射或关键字中的键是原子。
您应该使用Ecto.Changeset.cast/4
来应用验证,然后更新它是否有效。
答案 1 :(得分:0)
不要使用它:
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