diff --git a/lib/ecto/changeset.ex b/lib/ecto/changeset.ex index f79066955f..348c8e12de 100644 --- a/lib/ecto/changeset.ex +++ b/lib/ecto/changeset.ex @@ -581,6 +581,8 @@ defmodule Ecto.Changeset do end end + defp relation_changed?(:one, nil), do: true + defp relation_changed?(:one, changeset) do changeset.action != :update or changeset.changes != %{} end diff --git a/test/ecto/changeset_test.exs b/test/ecto/changeset_test.exs index 3f1b7910b6..6acd37f956 100644 --- a/test/ecto/changeset_test.exs +++ b/test/ecto/changeset_test.exs @@ -98,6 +98,8 @@ defmodule Ecto.ChangesetTest do belongs_to :category, Ecto.ChangesetTest.Category, references: :category_id, source: :cat_id has_many :comments, Ecto.ChangesetTest.Comment, on_replace: :delete has_one :comment, Ecto.ChangesetTest.Comment + has_one :deletable_comment, Ecto.ChangesetTest.Comment, on_replace: :delete + has_one :nilify_comment, Ecto.ChangesetTest.Comment, on_replace: :nilify end end @@ -878,6 +880,26 @@ defmodule Ecto.ChangesetTest do end end + test "changed?/3 returns true when a cardinality-one association is removed" do + comment = %Comment{id: 1} + + changeset = + %Post{deletable_comment: comment} + |> change() + |> put_assoc(:deletable_comment, nil) + + assert changeset.changes.deletable_comment == nil + assert changed?(changeset, :deletable_comment) + + changeset = + %Post{nilify_comment: comment} + |> cast(%{"nilify_comment" => nil}, []) + |> cast_assoc(:nilify_comment) + + assert changeset.changes.nilify_comment == nil + assert changed?(changeset, :nilify_comment) + end + test "fetch_field/2" do changeset = changeset(%Post{body: "bar"}, %{"title" => "foo"})