Can I use cast_assoc when the associated data is unique?

The example presented here is an abstraction. Assume external text input, “country” in this case should be unique. But I get (Ecto.ConstraintError) when I insert duplicates.

%Account{} |> Repo.preload(:country) |> Account.changeset(%{name: "Duck", country: %{name: "USA"} }) |> Ecto.Changeset.cast_assoc(:country, with: &Country.changeset/2) |> Repo.insert()

The :on_conflict option does not work in this case, or I didn’t use the right syntax: Repo.insert(on_conflict: [ set: [updated_at: now()] ], conflict_target: :name)

I think cast_assoc is the only way to insert all associated data with a single query. For simplicity I only included a single relation; I know about the other functions but I think those would require to execute more queries, so I don’t know which is the best practice.

What does the Account schema and migration look like?

What does the Country changeset/2, schema, and migration look like?

Thanks for suggestions @rih
I think the same issue was mentioned before:
https://groups.google.com/forum/#!topic/elixir-ecto/3SiKFJkLhc8

The answer to my question is that it would be too complex.

This is a bit late, but it might help someone with the same/similar issue.

I had a similar issue and solved it by adding the repo_opts property to the changeset on which I wanted to handle the unique constraint:

defmodule Country do
  # ...schema definition...

  def changeset(country, attrs) do
    country
    |> cast(attrs, [...])
    |> validate_required([...])
    # the repo_opts is an escape hatch that can be used on changesets
    |> Map.put(:repo_opts, [on_conflict: :replace_all, conflict_target: :name])
  end
end


# This will be inserted properly
%Account{}
|> Repo.preload(:country)
|> Account.changeset(%{name: "Duck", country: %{name: "USA"} })
|> Ecto.Changeset.cast_assoc(:country, with: &Country.changeset/2)
|> Repo.insert()

Reference: