Search code examples
elixirphoenix-frameworkecto

Insert/Update nested objects in ecto model


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?


Solution

  • 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