title: Updating records that use embeds_many
body: <p>I'm building an app in Elixir on top of the Phoenix Framework that has a piece of functionality around collecting data from the Spotify API and persisting it into a PostgreSQL 9.4 database for quick access. I'm having trouble with updating existing table rows that use <code>embeds_many</code>.</p>
  
  <p>I have Track and AlbumArt Ecto models that looks like this:</p>
  
  <pre><code>defmodule CoolApp.Track do
    use CoolApp.Web, :model
  
    alias CoolApp.AlbumArt
    alias CoolApp.Repo
    alias CoolApp.Track
  
    schema "tracks" do
      field :sid, :string
      field :title, :string
      field :artist, :string
      field :artist_sid, :string
      field :album, :string
      field :album_sid, :string
      field :sort_order, :integer
      field :is_now_playing, :boolean
  
      # embeds_many :album_art, AlbumArt
      # added on_replace: :delete
      embeds_many :album_art, AlbumArt, on_replace: :delete
  
      timestamps
    end
  end
  
  defmodule CoolApp.AlbumArt do
    use CoolApp.Web, :model
  
    embedded_schema do
      field :width, :integer
      field :height, :integer
      field :url, :string
    end
  end
  </code></pre>
  
  <p>The <code>*_sid</code> fields are the spotify IDs. The embedded <code>album_art</code> column is an array of data like:</p>
  
  <pre><code>{
    "height": 600,
    "width": 600,
    "url": "https://....."
  }
  </code></pre>
  
  <p>What I'm trying to do is go through an API response, normalize the data to match my schema, then iterate through it and update it in the database. The code that I have works fine for inserts, but completely fails on updates:</p>
  
  <pre><code>  def persist_track(track_params, sort_order) do
      album_art_params = transform_json_album_art_params(track_params.album_art)
  
      track_params =
        track_params
        |&gt; Map.delete(:album_art)
        |&gt; Map.put(:sort_order, sort_order)
  
      try do
        Repo.get_by!(Track, sid: track_params.sid)
        |&gt; Track.changeset(track_params)
        |&gt; Ecto.Changeset.put_change(:album_art, album_art_params)
        |&gt; Repo.update!
      rescue
        Ecto.NoResultsError -&gt;
          Track.changeset(%Track{}, track_params)
          |&gt; Ecto.Changeset.put_change(:album_art, album_art_params)
          |&gt; Repo.insert!
        error -&gt;
          raise error
  
      end
    end
  </code></pre>
  
  <p>The reason that I go through and update each one is primarily to refresh     the data, but also to update the <code>sort_order</code> if that's changed.</p>
  
  <p>When that code runs, for updates, I get back:</p>
  
  <pre><code>** (RuntimeError) you are attempting to change relation :album_art of
  CoolApp.Track, but there is missing data.
  
  By default, if the parent model contains N children, at least the same
  N children must be given on update. In other words, it is not possible
  to orphan embed nor associated records, attempting to do so results
  in this error message.
  
  It is possible to change this behaviour by setting :on_replace when
  defining the relation. See `Ecto.Changeset`'s section on related models
  for more info.
  </code></pre>
  
  <p>I've read a bit about the <code>:on_replace</code> setting and tried <code>:delete</code>, but to no avail. I just want to clobber that column with the new settings each time. is this even possible?</p>
  
  <p>EDIT: I went back in git history and tried to re-create my situation and discovered that seeing <code>:on_replace</code> to <code>:delete</code> actually does solve the problem. Because I didn't commit the exact situation that I was in, I'm not 100% sure if I was missing some other minor issue. I've got to make it a habit to hold onto my state better for questions on here.</p>