Ecto changeset - 跳过nil字段

时间:2017-07-09 05:18:30

标签: elixir ecto elixir-framework

如果字段不为零,如何向changeset添加字段?如果值为nil,我不想更新数据库中的值。我需要检查3个字段,只更新那些不是nil的字段。

当前代码:

  put "/products" do
    errors = {}
    IO.inspect(conn.body_params)

    product = Api.Product |> Api.Repo.get(conn.query_params["id"])
    IO.inspect(product)

    if conn.body_params["image"] do
      changeset = Api.Product.changeset(product, %{image: conn.body_params["image"]})
    end

    if conn.body_params["description"] do
      changeset = Api.Product.changeset(product, %{description: conn.body_params["description"]})
    end

    if conn.body_params["price"] do
      changeset = Api.Product.changeset(product, %{price: conn.body_params["price"]})
    end
    case Api.Repo.update(changeset) do
      {:ok, product} -> 
        errors = Tuple.append(errors, "Product updated")
      {:error, changeset} -> 
        errors = Tuple.append(errors, "Product not updated")
    end

    conn
      |> put_resp_content_type("application/json")
      |> send_resp(200, Poison.encode!(%{
          successs: "success",
          errors: Tuple.to_list(errors)
      }))
  end

2 个答案:

答案 0 :(得分:1)

您可以使用for创建一个仅包含架构所接受的键且其值不为零的新params地图,并将其传递给changeset/2

product = Api.Product |> Api.Repo.get(conn.query_params["id"])
params = for key <- ~w(image description price), value = conn.body_params[key], into: %{}, do: {key, value}
changeset = Api.Product.changeset(product, params)
case Api.Repo.update(changeset) do
  ...
end

答案 1 :(得分:0)

这是validate_required/3的用途。 https://hexdocs.pm/ecto/Ecto.Changeset.html#validate_required/3

您将变更集和必填字段列表作为原子传递给它。如果任何指定的字段不存在(即nil),则会在您的变更集中添加错误,并且该错误也会被标记为无效。

iex> changeset |> validate_required([:field1, :field2, :field3])
%Ecto.Changeset{valid?: false, errors: %{"field1" => ["can't be blank"]}}

PS。你不需要像上面那样自己管理错误。错误将自动添加到changeset.errors的变更集中。