Skip to content

Commit 3bc8755

Browse files
authored
feat(Ecto.Schema): Add option to skip validations for default values (#3749)
1 parent 0e8954d commit 3bc8755

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

lib/ecto/schema.ex

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,16 @@ defmodule Ecto.Schema do
645645
## Options
646646
647647
* `:default` - Sets the default value on the schema and the struct.
648+
648649
The default value is calculated at compilation time, so don't use
649650
expressions like `DateTime.utc_now` or `Ecto.UUID.generate` as
650651
they would then be the same for all records: in this scenario you can use
651-
the `:autogenerate` option to generate at insertion time.
652+
the `:autogenerate` option to generate at insertion time.
653+
654+
The default value is validated against the field's type at compilation time
655+
and it will raise an ArgumentError if there is a type mismatch. If you cannot
656+
infer the field's type at compilation time, you can use the
657+
`:skip_default_validation` option on the field to skip validations.
652658
653659
Once a default value is set, if you send changes to the changeset that
654660
contains the same value defined as default, validations will not be performed
@@ -685,6 +691,9 @@ defmodule Ecto.Schema do
685691
when inspected in changes inside a `Ecto.Changeset` and be excluded
686692
from inspect on the schema. Defaults to `false`.
687693
694+
* `:skip_default_validation` - When true, it will skip the type validation
695+
step at compile time.
696+
688697
"""
689698
defmacro field(name, type \\ :string, opts \\ []) do
690699
quote do
@@ -1881,7 +1890,7 @@ defmodule Ecto.Schema do
18811890

18821891
type = check_field_type!(mod, name, type, opts)
18831892
Module.put_attribute(mod, :changeset_fields, {name, type})
1884-
validate_default!(type, opts[:default])
1893+
validate_default!(type, opts[:default], opts[:skip_default_validation])
18851894
define_field(mod, name, type, opts)
18861895
end
18871896

@@ -2141,7 +2150,8 @@ defmodule Ecto.Schema do
21412150
Module.put_attribute(mod, :struct_fields, {name, assoc})
21422151
end
21432152

2144-
defp validate_default!(type, value) do
2153+
defp validate_default!(_type, _value, true), do: :ok
2154+
defp validate_default!(type, value, _skip) do
21452155
case Ecto.Type.dump(type, value) do
21462156
{:ok, _} ->
21472157
:ok

test/ecto/schema_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,17 @@ defmodule Ecto.SchemaTest do
418418
end
419419
end
420420

421+
test "skipping validations on invalid types" do
422+
defmodule SchemaSkipValidationsDefault do
423+
use Ecto.Schema
424+
425+
schema "invalid_default" do
426+
# Without skip_default_validation this would fail to compile
427+
field :count, :integer, default: "1", skip_default_validation: true
428+
end
429+
end
430+
end
431+
421432
test "invalid field type" do
422433
assert_raise ArgumentError, "invalid or unknown type {:apa} for field :name", fn ->
423434
defmodule SchemaInvalidFieldType do

0 commit comments

Comments
 (0)