Search code examples
elixirphoenix-frameworkecto

Ecto Reload belongs_to Association After Successful Repo.update


Changing the association of a given child from parent_a to parent_b via parent_id in params leaves a stale record.parent object.

e.g. (assume params matches %{child: %{id: '1', parent_id: '6'}})

# ...
child = Repo.get(Child, child_id)
|> preload([:parent])
changeset = Child.changeset(child, child_params)

case Repo.update(changeset) do
  {:ok, child} ->
    IO.puts child.parent_id # returns '6', or the new, changed `id`
    IO.puts child.parent.id # returns '5', or the old id
                            # child.parent is stale
# ...

What is the proper way to retrieve the newly associated parent record after updating?


Solution

  • There is no built in way to do this in Ecto for now. You also have the issue that you can't use preload, as the association has already been preloaded.

    One option is this:

    %{child | parent: Repo.get!(Parent, child.parent_id)}
    

    You can also choose to not call preload until after you call Repo.update which will prevent the association already being loaded.