@@ -18,7 +18,7 @@ defmodule EctoTypedSchema.FieldMacros do
1818 @ spec field ( atom ( ) , atom ( ) | module ( ) , keyword ( ) ) :: Macro . t ( )
1919 defmacro field ( name , type \\ :string , opts \\ [ ] ) do
2020 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
21- validate_typed_option! ( name , typed )
21+ typed = sanitize_typed_opts ( typed )
2222
2323 # Propagate non-nil Ecto defaults to typed opts so TypedStructor sees them,
2424 # unless the field is explicitly nullable (null: true).
@@ -50,34 +50,31 @@ defmodule EctoTypedSchema.FieldMacros do
5050 end
5151 end
5252
53- @ spec validate_typed_option! ( atom ( ) , term ( ) ) :: :ok
54- defp validate_typed_option! ( field_name , typed ) do
55- unless Keyword . keyword? ( typed ) do
56- raise ArgumentError ,
57- "field :#{ field_name } option :typed must be a keyword list, got: #{ inspect ( typed ) } "
58- end
53+ @ supported_typed_keys [ :type , :null , :default , :enum_values , :through , :foreign_key ]
5954
60- :ok
61- end
55+ @ spec sanitize_typed_opts ( keyword ( ) ) :: keyword ( )
56+ defp sanitize_typed_opts ( typed ) , do: Keyword . take ( typed , @ supported_typed_keys )
6257
6358 @ spec belongs_to ( atom ( ) , module ( ) , keyword ( ) ) :: Macro . t ( )
6459 defmacro belongs_to ( name , schema , opts \\ [ ] ) do
6560 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
66- validate_typed_option! ( name , typed )
61+ typed = sanitize_typed_opts ( typed )
6762 { foreign_key_typed , typed } = Keyword . pop ( typed , :foreign_key , [ ] )
6863
69- # Propagate null/enforce from association to FK unless FK explicitly overrides
70- foreign_key_typed =
71- typed
72- |> Keyword . take ( [ :null , :enforce ] )
73- |> Keyword . merge ( foreign_key_typed )
74-
7564 foreign_key =
7665 case Keyword . fetch ( opts , :foreign_key ) do
7766 :error -> :"#{ name } _id"
7867 { :ok , value } -> value
7968 end
8069
70+ foreign_key_typed = sanitize_typed_opts ( foreign_key_typed )
71+
72+ # Propagate null from association to FK unless FK explicitly overrides
73+ foreign_key_typed =
74+ typed
75+ |> Keyword . take ( [ :null ] )
76+ |> Keyword . merge ( foreign_key_typed )
77+
8178 define_field = Keyword . get ( opts , :define_field , true )
8279
8380 quote location: :keep do
@@ -94,7 +91,7 @@ defmodule EctoTypedSchema.FieldMacros do
9491 @ spec has_one ( atom ( ) , module ( ) | keyword ( ) , keyword ( ) ) :: Macro . t ( )
9592 defmacro has_one ( name , schema , opts \\ [ ] ) do
9693 { typed , schema , opts } = extract_has_typed_opts ( schema , opts )
97- validate_typed_option! ( name , typed )
94+ typed = sanitize_typed_opts ( typed )
9895
9996 quote location: :keep do
10097 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -106,7 +103,7 @@ defmodule EctoTypedSchema.FieldMacros do
106103 @ spec embeds_one ( atom ( ) , module ( ) , keyword ( ) ) :: Macro . t ( )
107104 defmacro embeds_one ( name , schema , opts \\ [ ] ) do
108105 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
109- validate_typed_option! ( name , typed )
106+ typed = sanitize_typed_opts ( typed )
110107
111108 quote location: :keep do
112109 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -118,7 +115,7 @@ defmodule EctoTypedSchema.FieldMacros do
118115 @ spec embeds_one ( atom ( ) , module ( ) , keyword ( ) , keyword ( ) ) :: Macro . t ( )
119116 defmacro embeds_one ( name , schema , opts , do: block ) do
120117 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
121- validate_typed_option! ( name , typed )
118+ typed = sanitize_typed_opts ( typed )
122119
123120 quote location: :keep do
124121 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -130,7 +127,7 @@ defmodule EctoTypedSchema.FieldMacros do
130127 @ spec embeds_many ( atom ( ) , module ( ) , keyword ( ) ) :: Macro . t ( )
131128 defmacro embeds_many ( name , schema , opts \\ [ ] ) do
132129 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
133- validate_typed_option! ( name , typed )
130+ typed = sanitize_typed_opts ( typed )
134131
135132 quote location: :keep do
136133 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -142,7 +139,7 @@ defmodule EctoTypedSchema.FieldMacros do
142139 @ spec embeds_many ( atom ( ) , module ( ) , keyword ( ) , keyword ( ) ) :: Macro . t ( )
143140 defmacro embeds_many ( name , schema , opts , do: block ) do
144141 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
145- validate_typed_option! ( name , typed )
142+ typed = sanitize_typed_opts ( typed )
146143
147144 quote location: :keep do
148145 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -154,7 +151,7 @@ defmodule EctoTypedSchema.FieldMacros do
154151 @ spec has_many ( atom ( ) , module ( ) | keyword ( ) , keyword ( ) ) :: Macro . t ( )
155152 defmacro has_many ( name , schema , opts \\ [ ] ) do
156153 { typed , schema , opts } = extract_has_typed_opts ( schema , opts )
157- validate_typed_option! ( name , typed )
154+ typed = sanitize_typed_opts ( typed )
158155
159156 quote location: :keep do
160157 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -166,7 +163,7 @@ defmodule EctoTypedSchema.FieldMacros do
166163 @ spec many_to_many ( atom ( ) , module ( ) , keyword ( ) ) :: Macro . t ( )
167164 defmacro many_to_many ( name , schema , opts \\ [ ] ) do
168165 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
169- validate_typed_option! ( name , typed )
166+ typed = sanitize_typed_opts ( typed )
170167
171168 quote location: :keep do
172169 @ ecto_typed_schema_typed { unquote ( name ) , unquote ( Macro . escape ( typed ) ) }
@@ -178,7 +175,7 @@ defmodule EctoTypedSchema.FieldMacros do
178175 @ spec timestamps ( keyword ( ) ) :: Macro . t ( )
179176 defmacro timestamps ( opts \\ [ ] ) do
180177 { typed , opts } = Keyword . pop ( opts , :typed , [ ] )
181- validate_typed_option! ( :timestamps , typed )
178+ typed = sanitize_typed_opts ( typed )
182179
183180 quote location: :keep do
184181 # Merge @timestamps_opts (if defined) with explicit opts.
0 commit comments