0
votes

With a model such as

defmodule MyApp.StorageMovement do
  use MyApp.Web, :model

  schema "storage_movements" do
    field :name, :string
    field :reference_datetime, Timex.Ecto.DateTime
    has_many :storage_product_movements, MyApp.StorageProductMovement

    timestamps()
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(parse_params_date(params), [:name, :reference_datetime])
    |> validate_required([:name, :reference_datetime])
  end
end

how can with a single post request, upsert the associated values? Like, if it contains something with an ID, update it, if it's without the ID, create it etc?

2

2 Answers

1
votes

Just found out that if you change the model like this:

defmodule MyApp.StorageMovement do
  use MyApp.Web, :model

  schema "storage_movements" do
    field :name, :string
    field :reference_datetime, Timex.Ecto.DateTime
    has_many :storage_product_movements, MyApp.StorageProductMovement, on_replace: :delete

    timestamps()
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(parse_params_date(params), [:name, :reference_datetime])
    |> cast_assoc(:storage_product_movements, params["storage_product_movements"])
    |> validate_required([:name, :reference_datetime])
  end
end

it will automatically go through the params child array and create new entities if they don't have an ID, delete those existant on the database but not in the params array and update those with an ID

-1
votes

I think you're looking for insert_or_update/2.

From the docs:

result =
  case MyRepo.get(Post, id) do
    nil  -> %Post{id: id} # Post not found, we build one
    post -> post          # Post exists, let's use it
  end
  |> Post.changeset(changes)
  |> MyRepo.insert_or_update

case result do
  {:ok, struct}       -> # Inserted or updated with success
  {:error, changeset} -> # Something went wrong
end