验证Elixir Ecto中的状态,但仅限于插入或更新

Ell*_*son 2 elixir ecto

要验证参数的存在,可以向required_fields模型中的模块属性添加字段.然后将其传递给模型的cast方法,该方法验证该字段是否存在.

但是,如果您只想在插入或更新时验证某些内容的存在,该怎么办?

例如,如果记录没有保留,我只想验证用户的密码是否存在.换句话说,我不希望用户在编辑其帐户信息时必须提供密码.

我提出的最好的方法是为更新和插入提供两组不同的必填字段,然后让方法选择适当的方法:

# in changeset method
cast(params, required_fields(model), @optional_fields)

defp required_fields(model) do
  if Map.has_key?(model, :id) do
    @update_required_fields
  else
    @insert_required_fields
  end
end
Run Code Online (Sandbox Code Playgroud)

这是合理的,还是有更好的方法?

编辑

添加来自@michalmuskala的建议,并添加有关共享变更集功能的后续问题:

def insert_changeset(model, params \\ :empty) do
  model
  |> cast(params, @insert_required_fields, @insert_optional_fields)
  |> shared_changeset
end

def update_changeset(model, params \\ :empty) do
  model
  |> cast(params, @update_required_fields, @update_optional_fields)
  |> shared_changeset
end

defp shared_changeset(changeset) do
  changeset
  |> validate_password
  |> unique_constraint(:email)
end
Run Code Online (Sandbox Code Playgroud)

mic*_*ala 6

最简单的解决方案是创建两个变更集功能 - 一个用于插入,另一个用于更新.所以你最终会得到类似的东西:

def update_changeset(model, params \\ :empty) do
  model
  |> cast(params, @update_required_fields, @optional_fields)
end

def insert_changeset(model, params \\ :empty) do
  model
  |> cast(params, @insert_required_fields, @optional_fields)
end
Run Code Online (Sandbox Code Playgroud)

然后在控制器中,而不是叫Model.changeset/2你打电话Model.update_changeset/2Model.insert_changeset/2.