diff --git a/lib/ash/actions/create.ex b/lib/ash/actions/create.ex index bb1ffb54..f0ea6cb9 100644 --- a/lib/ash/actions/create.ex +++ b/lib/ash/actions/create.ex @@ -76,7 +76,7 @@ defmodule Ash.Actions.Create do else Ash.Changeset.for_create(changeset, action.name, %{}, actor: actor) end - |> Ash.Changeset.set_defaults(:create) + |> Ash.Changeset.set_defaults(:create, true) |> Ash.Changeset.cast_arguments(action) end diff --git a/lib/ash/actions/update.ex b/lib/ash/actions/update.ex index 8885c91c..8f3d9401 100644 --- a/lib/ash/actions/update.ex +++ b/lib/ash/actions/update.ex @@ -74,7 +74,7 @@ defmodule Ash.Actions.Update do else Ash.Changeset.for_update(changeset, action.name, %{}, actor: actor) end - |> Ash.Changeset.set_defaults(:update) + |> Ash.Changeset.set_defaults(:update, true) |> Ash.Changeset.cast_arguments(action) end diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index 7c6ac3b9..651327bd 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -280,11 +280,6 @@ defmodule Ash.Changeset do tenant: [ type: :any, doc: "set the tenant on the changeset" - ], - defaults: [ - type: :any, - doc: - "A list of attributes and arguments to apply defaults for. Defaults to: []. Any unset defaults are set when the action is called." ] ] @@ -450,7 +445,7 @@ defmodule Ash.Changeset do |> validate_relationships_accepted(action) |> cast_arguments(action, opts[:defaults], true) |> run_action_changes(action, opts[:actor]) - |> set_defaults(changeset.action_type, opts[:defaults] || []) + |> set_defaults(changeset.action_type, false) |> add_validations() |> require_values(changeset.action_type) |> mark_validated(action.name) @@ -585,13 +580,16 @@ defmodule Ash.Changeset do end @doc false - def set_defaults(changeset, action_type, keys \\ :all) + def set_defaults(changeset, action_type, lazy? \\ false) - def set_defaults(changeset, :create, keys) do + def set_defaults(changeset, :create, lazy?) do changeset.resource |> Ash.Resource.Info.attributes() |> Enum.filter(&(not is_nil(&1.default))) - |> Enum.filter(&(keys == :all || &1.name in keys)) + |> Enum.filter(fn attribute -> + lazy? or + not (is_function(attribute.default) or match?({_, _, _}, attribute.default)) + end) |> Enum.reduce(changeset, fn attribute, changeset -> force_change_new_attribute_lazy(changeset, attribute.name, fn -> default(:create, attribute) @@ -599,11 +597,14 @@ defmodule Ash.Changeset do end) end - def set_defaults(changeset, :update, keys) do + def set_defaults(changeset, :update, lazy?) do changeset.resource |> Ash.Resource.Info.attributes() |> Enum.filter(&(not is_nil(&1.update_default))) - |> Enum.filter(&(keys == :all || &1.name in keys)) + |> Enum.filter(fn attribute -> + lazy? or + not (is_function(attribute.update_default) or match?({_, _, _}, attribute.update_default)) + end) |> Enum.reduce(changeset, fn attribute, changeset -> force_change_new_attribute_lazy(changeset, attribute.name, fn -> default(:update, attribute) diff --git a/lib/ash/query/query.ex b/lib/ash/query/query.ex index e4fab9bc..adaf382b 100644 --- a/lib/ash/query/query.ex +++ b/lib/ash/query/query.ex @@ -217,11 +217,6 @@ defmodule Ash.Query do tenant: [ type: :any, doc: "set the tenant on the query" - ], - defaults: [ - type: :any, - doc: - "A list of arguments to apply defaults for. Defaults to: []. Any unset defaults are set when the action is called." ] ] @@ -257,7 +252,7 @@ defmodule Ash.Query do |> cast_params(action, args) |> run_preparations(action, opts[:actor]) |> add_action_filters(action, opts[:actor]) - |> cast_arguments(action, opts[:defaults], true) + |> cast_arguments(action, true) else add_error(query, :action, "No such action #{action_name}") end @@ -801,22 +796,18 @@ defmodule Ash.Query do end @doc false - def cast_arguments(query, action, defaults \\ :all, only_supplied? \\ false) do + def cast_arguments(query, action, only_supplied? \\ false) do action.arguments |> Enum.reject(& &1.private?) |> Enum.reject(&(only_supplied? && match?({:ok, _}, fetch_argument(query, &1.name)))) |> Enum.reduce(query, fn argument, new_query -> - {ignore_nil_check, value} = - if defaults == :all || argument.name in (defaults || []) do - {false, get_argument(query, argument.name) || argument_default(argument.default)} - else - value = get_argument(query, argument.name) + value = get_argument(query, argument.name) - if argument_default(argument.default) do - {true, value} - else - {false, value} - end + {ignore_nil_check, value} = + if argument_default(argument.default) do + {true, value} + else + {false, value} end cond do diff --git a/lib/ash/resource/attribute.ex b/lib/ash/resource/attribute.ex index d93cf1ff..afde8c84 100644 --- a/lib/ash/resource/attribute.ex +++ b/lib/ash/resource/attribute.ex @@ -82,12 +82,12 @@ defmodule Ash.Resource.Attribute do update_default: [ type: {:custom, Ash.OptionsHelpers, :default, []}, doc: - "A zero argument function, an {mod, fun, args} triple or a value. If no value is provided for the attribute on update, this value is used." + "A zero argument function, an {mod, fun, args} triple or a value. `Ash.Changeset.for_update/4` sets the default in the changeset if a value is not provided." ], default: [ type: {:custom, Ash.OptionsHelpers, :default, []}, doc: - "A zero argument function, an {mod, fun, args} triple or a value. If no value is provided for the attribute on create, this value is used." + "A zero argument function, an {mod, fun, args} triple or a value. `Ash.Changeset.for_create/4` sets the default in the changeset if a value is not provided." ], description: [ type: :string, @@ -106,7 +106,10 @@ defmodule Ash.Resource.Attribute do |> OptionsHelpers.set_default!(:writable?, false) |> OptionsHelpers.set_default!(:private?, true) |> OptionsHelpers.set_default!(:default, &DateTime.utc_now/0) - |> OptionsHelpers.set_default!(:update_default, &DateTime.utc_now/0) + |> OptionsHelpers.set_default!( + :update_default, + &DateTime.utc_now/0 + ) |> OptionsHelpers.set_default!(:type, Ash.Type.UtcDatetimeUsec) |> OptionsHelpers.set_default!(:allow_nil?, false)