Skip to content

Commit 576665f

Browse files
authored
Add support for :writable option on belongs_to (#4624)
1 parent db12e07 commit 576665f

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

lib/ecto/schema.ex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,12 @@ defmodule Ecto.Schema do
11061106
* `:where` - A filter for the association. See "Filtering associations"
11071107
in `has_many/3`.
11081108
1109+
* `:writable` - Defines when the underlying field is allowed to modified, Must be
1110+
one of `:always`, `:insert`, or `:never`. If set to `:always`, the field can be
1111+
modified by any repo operation. If set to `:insert`, the field can be inserted
1112+
but cannot be further modified, even in an upsert. If set to `:never`, the field
1113+
becomes read only. Defaults to `:always`.
1114+
11091115
## Examples
11101116
11111117
defmodule Comment do
@@ -2138,6 +2144,7 @@ defmodule Ecto.Schema do
21382144
:defaults,
21392145
:primary_key,
21402146
:source,
2147+
:writable,
21412148
:where
21422149
]
21432150

test/ecto/repo/belongs_to_test.exs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ defmodule Ecto.Repo.BelongsToTest do
3535
end
3636
end
3737

38+
defmodule RestrictedSchema do
39+
use Ecto.Schema
40+
41+
schema "restricted_schema" do
42+
belongs_to :unwritable, MyAssoc, writable: :never
43+
belongs_to :non_updatable, MyAssoc, writable: :insert
44+
end
45+
end
46+
3847
test "handles assocs on insert" do
3948
sample = %MyAssoc{x: "xyz"}
4049

@@ -496,4 +505,29 @@ defmodule Ecto.Repo.BelongsToTest do
496505
assert updated_schema.assoc_id == 2
497506
assert %Ecto.Association.NotLoaded{} = updated_schema.assoc
498507
end
508+
509+
test "handles writable: :never" do
510+
schema =
511+
%RestrictedSchema{}
512+
|> Ecto.Changeset.cast(%{unwritable_id: 111}, [:unwritable_id])
513+
|> TestRepo.insert!()
514+
515+
assert schema.unwritable_id == nil
516+
end
517+
518+
test "handles writable: :insert" do
519+
schema =
520+
%RestrictedSchema{}
521+
|> Ecto.Changeset.cast(%{non_updatable_id: 222}, [:non_updatable_id])
522+
|> TestRepo.insert!()
523+
524+
assert schema.non_updatable_id == 222
525+
526+
schema =
527+
schema
528+
|> Ecto.Changeset.cast(%{non_updatable_id: 333}, [:non_updatable_id])
529+
|> TestRepo.update!()
530+
531+
assert schema.non_updatable_id == 222
532+
end
499533
end

0 commit comments

Comments
 (0)