Setting :on_replace to :nilify does not work

Hi I’ve association between User and Credential.

User schema:

defmodule Burn.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias Burn.Accounts.{User, Credential}


  schema "users" do
    field :bio, :string
    field :fullname, :string
    field :username, :string
    has_one :credential, Credential

    timestamps()
  end

  @doc false
  def changeset(%User{} = user, attrs) do
    user
    |> cast(attrs, [:username, :fullname, :bio])
    |> validate_required([:username])
    |> unique_constraint(:username)
  end
end

Credential schema:

defmodule Burn.Accounts.Credential do
  use Ecto.Schema
  import Ecto.Changeset
  alias Burn.Accounts.{Credential, User}


  schema "credentials" do
    field :email, :string
    belongs_to :user, User, on_replace: :nilify

    timestamps()
  end

  @doc false
  def changeset(%Credential{} = credential, attrs) do
    credential
    |> cast(attrs, [:email])
    |> validate_required([:email])
    |> unique_constraint(:email)
  end
end

it’s simple! but when I wanna cast and prepare the changeset for the update query by:

user
|> User.changeset(%{bio: "some bio", credential: %{email: "some@email.com"}})
|> Ecto.Changeset.cast_assoc(:credential, with: &Credential.changeset/2)

I get this error:

(RuntimeError) you are attempting to change relation :credential of
Burn.Accounts.User but the :on_replace option of
this relation is set to :raise

even I’ve on_replace: :nilify on Credential

  • Elixir 1.4.5
  • phoenix 1.3.0

Finally now I get it work after add ID of Credential in params like this:

user
|> User.changeset(%{bio: "some bio", credential: %{email: "some@email.com", id: user.credential.id}})
|> Ecto.Changeset.cast_assoc(:credential, with: &Credential.changeset/2)
1 Like