diff --git a/lib/ash/resource.ex b/lib/ash/resource.ex index fb551e4a..4409329a 100644 --- a/lib/ash/resource.ex +++ b/lib/ash/resource.ex @@ -372,6 +372,17 @@ defmodule Ash.Resource do end end + @doc "Returns the configured default actions" + @spec default_actions(Ash.resource()) :: [:create | :read | :update | :destroy] + def default_actions(resource) do + Extension.get_opt( + resource, + [:actions], + :defaults, + [:create, :read, :update, :destroy] + ) + end + @doc "Returns all actions of a resource" @spec actions(Ash.resource()) :: [Ash.action()] def actions(resource) do diff --git a/lib/ash/resource/dsl.ex b/lib/ash/resource/dsl.ex index d41b51e2..afe698f1 100644 --- a/lib/ash/resource/dsl.ex +++ b/lib/ash/resource/dsl.ex @@ -420,6 +420,19 @@ defmodule Ash.Resource.Dsl do imports: [ Ash.Resource.Change.Builtins ], + schema: [ + defaults: [ + type: {:list, {:in, [:create, :read, :update, :destroy]}}, + default: [:create, :read, :update, :destroy], + doc: """ + By default, an action of each type is added to each resource. + + If any other actions of that same type are added, the default of that type is *not* + added. If you wish to skip adding defaults of certain types, specify this option + with the defaults that you *do* want implemented. + """ + ] + ], examples: [ """ actions do diff --git a/lib/ash/resource/transformers/set_primary_actions.ex b/lib/ash/resource/transformers/set_primary_actions.ex index 091e33b3..5b4ff423 100644 --- a/lib/ash/resource/transformers/set_primary_actions.ex +++ b/lib/ash/resource/transformers/set_primary_actions.ex @@ -11,11 +11,30 @@ defmodule Ash.Resource.Transformers.SetPrimaryActions do alias Ash.Dsl.Transformer alias Ash.Error.Dsl.DslError - def transform(_resource, dsl_state) do + @extension Ash.Resource.Dsl + + def transform(resource, dsl_state) do dsl_state |> Transformer.get_entities([:actions]) |> Enum.group_by(& &1.type) + |> Map.put_new(:read, []) + |> Map.put_new(:update, []) + |> Map.put_new(:create, []) + |> Map.put_new(:destroy, []) |> Enum.reduce_while({:ok, dsl_state}, fn + {type, []}, {:ok, dsl_state} -> + if type in Ash.Resource.default_actions(resource) do + {:ok, action} = + Transformer.build_entity(@extension, [:actions], type, + name: type, + primary?: true + ) + + {:cont, {:ok, Transformer.add_entity(dsl_state, [:actions], action)}} + else + {:cont, {:ok, dsl_state}} + end + {type, [action]}, {:ok, dsl_state} -> {:cont, {:ok, diff --git a/mix.exs b/mix.exs index 05ae898d..a503248f 100644 --- a/mix.exs +++ b/mix.exs @@ -142,7 +142,7 @@ defmodule Ash.MixProject do {:sobelow, ">= 0.0.0", only: :dev, runtime: false}, {:git_ops, "~> 2.0.1", only: :dev}, {:picosat_elixir, "~> 0.1.5"}, - {:nimble_options, "~> 0.3.0"}, + {:nimble_options, "~> 0.3.5"}, {:excoveralls, "~> 0.13.0", only: [:dev, :test]}, {:mix_test_watch, "~> 1.0", only: :dev, runtime: false}, {:parse_trans, "3.3.0", only: [:dev, :test], override: true} diff --git a/test/resource/actions/actions_test.exs b/test/resource/actions/actions_test.exs index 7a5cea31..a5e7bab0 100644 --- a/test/resource/actions/actions_test.exs +++ b/test/resource/actions/actions_test.exs @@ -19,6 +19,13 @@ defmodule Ash.Test.Dsl.Resource.Actions.ActionsTest do end end + test "default actions are added" do + defposts do + end + + assert Ash.Resource.primary_action!(Post, :read) + end + describe "validations" do test "raises if you have multiple primary actions for a type" do assert_raise( diff --git a/test/resource/actions/create_test.exs b/test/resource/actions/create_test.exs index 848e1f7f..5238b770 100644 --- a/test/resource/actions/create_test.exs +++ b/test/resource/actions/create_test.exs @@ -22,6 +22,7 @@ defmodule Ash.Test.Dsl.Resource.Actions.CreateTest do test "it creates an action" do defposts do actions do + defaults([]) create :default end end diff --git a/test/resource/actions/destroy_test.exs b/test/resource/actions/destroy_test.exs index 9f59aa92..5cc4fbc7 100644 --- a/test/resource/actions/destroy_test.exs +++ b/test/resource/actions/destroy_test.exs @@ -22,6 +22,7 @@ defmodule Ash.Test.Dsl.Resource.Actions.DestroyTest do test "it creates an action" do defposts do actions do + defaults([]) destroy :default end end diff --git a/test/resource/actions/read_test.exs b/test/resource/actions/read_test.exs index ee3d47fe..0096d5fd 100644 --- a/test/resource/actions/read_test.exs +++ b/test/resource/actions/read_test.exs @@ -22,6 +22,7 @@ defmodule Ash.Test.Dsl.Resource.Actions.ReadTest do test "it creates an action" do defposts do actions do + defaults([]) read :default end end diff --git a/test/resource/actions/update_test.exs b/test/resource/actions/update_test.exs index 3c91b70e..05bde2c2 100644 --- a/test/resource/actions/update_test.exs +++ b/test/resource/actions/update_test.exs @@ -20,6 +20,7 @@ defmodule Ash.Test.Dsl.Resource.Actions.UpdateTest do test "it creates an action" do defposts do actions do + defaults([]) update :default end end