Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/ecto/repo/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ defmodule Ecto.Repo.Schema do
case changes do
%{^field => _change} ->
handle_writable_violation(field, schema, action)
changes
Map.delete(changes, field)
%{} ->
changes
end
Expand Down
3 changes: 1 addition & 2 deletions lib/ecto/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -706,8 +706,7 @@ defmodule Ecto.Schema do
attempts to modify a field that should not be modified according to it's `:writable` value.
Must be one of `:nothing`, `:warn`, or `:raise`. If set to `:nothing`, the modification is
silently ignored. If set to `:warn`, the modification is ignored and a warning is logged. If set
to `:raise`, an exception is raised and the operation is aborted. If `:writable` is set to `:always`,
`:on_writable_violation` must be set to `:nothing`. Defaults to `:nothing`.
to `:raise`, an exception is raised and the operation is aborted. Defaults to `:nothing`.

"""
defmacro field(name, type \\ :string, opts \\ []) do
Expand Down
28 changes: 28 additions & 0 deletions test/ecto/repo_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2439,6 +2439,20 @@ defmodule Ecto.RepoTest do
]
end

test "update with on_writable_violation: :nothing/warn does not reflect ignored changes in returned struct" do
{:ok, %MySchemaWritable{always: 10, never: nil, insert: nil}} =
%MySchemaWritable{id: 1}
|> Ecto.Changeset.change(%{always: 10, never: 11, insert: 12})
|> TestRepo.update()

capture_log(fn ->
{:ok, %MySchemaWritableWarn{always: 10, never: nil, insert: nil}} =
%MySchemaWritableWarn{id: 1}
|> Ecto.Changeset.change(%{always: 10, never: 11, insert: 12})
|> TestRepo.update()
end)
end

test "update with on_writable_violation: :nothing saves changes for writable: :always and ignores changes for writable: :insert/:never" do
%MySchemaWritable{id: 1}
|> Ecto.Changeset.change(%{always: 10, never: 11, insert: 12})
Expand Down Expand Up @@ -2513,6 +2527,20 @@ defmodule Ecto.RepoTest do
end
end

test "insert with on_writable_violation: :nothing/warn does not reflect ignored changes in returned struct" do
{:ok, %MySchemaWritable{always: 10, never: nil, insert: 12}} =
%MySchemaWritable{id: 1}
|> Ecto.Changeset.change(%{always: 10, never: 11, insert: 12})
|> TestRepo.insert()

capture_log(fn ->
{:ok, %MySchemaWritableWarn{always: 10, never: nil, insert: 12}} =
%MySchemaWritableWarn{id: 2}
|> Ecto.Changeset.change(%{always: 10, never: 11, insert: 12})
|> TestRepo.insert()
end)
end

test "insert with surfaced changes on_writable_violation: :nothing saves changes for writable: :always/:insert and ignores changes for writable: :never" do
%MySchemaWritable{id: 1, always: 10, never: 11, insert: 12}
|> Ecto.Changeset.change(%{})
Expand Down
Loading