Skip to content

Commit 7165eb2

Browse files
committed
Remove accept, arguments from pipeline
1 parent 2a8065d commit 7165eb2

File tree

5 files changed

+36
-404
lines changed

5 files changed

+36
-404
lines changed

documentation/dsls/DSL-Ash.Resource.md

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3024,7 +3024,6 @@ that can be referenced from multiple actions via `pipe_through`.
30243024

30253025
### Nested DSLs
30263026
* [pipeline](#pipelines-pipeline)
3027-
* argument
30283027
* change
30293028
* validate
30303029
* prepare
@@ -3055,7 +3054,6 @@ that can be referenced from multiple actions via `pipe_through`.
30553054

30563055

30573056
### Nested DSLs
3058-
* [argument](#pipelines-pipeline-argument)
30593057
* [change](#pipelines-pipeline-change)
30603058
* [validate](#pipelines-pipeline-validate)
30613059
* [prepare](#pipelines-pipeline-prepare)
@@ -3082,52 +3080,8 @@ end
30823080
| Name | Type | Default | Docs |
30833081
|------|------|---------|------|
30843082
| [`description`](#pipelines-pipeline-description){: #pipelines-pipeline-description } | `String.t` | | An optional description for the pipeline |
3085-
| [`accept`](#pipelines-pipeline-accept){: #pipelines-pipeline-accept } | `atom \| list(atom) \| :*` | `[]` | A list of attributes to accept. Merged with the action's own accept list. |
3086-
3087-
3088-
### pipelines.pipeline.argument
3089-
```elixir
3090-
argument name, type
3091-
```
3092-
3093-
3094-
Declares an argument on the action
3095-
3096-
3097-
3098-
3099-
### Examples
3100-
```
3101-
argument :password_confirmation, :string
3102-
```
3103-
31043083

31053084

3106-
### Arguments
3107-
3108-
| Name | Type | Default | Docs |
3109-
|------|------|---------|------|
3110-
| [`name`](#pipelines-pipeline-argument-name){: #pipelines-pipeline-argument-name .spark-required} | `atom` | | The name of the argument |
3111-
| [`type`](#pipelines-pipeline-argument-type){: #pipelines-pipeline-argument-type .spark-required} | `module` | | The type of the argument. See `Ash.Type` for more. |
3112-
### Options
3113-
3114-
| Name | Type | Default | Docs |
3115-
|------|------|---------|------|
3116-
| [`description`](#pipelines-pipeline-argument-description){: #pipelines-pipeline-argument-description } | `String.t` | | An optional description for the argument. |
3117-
| [`constraints`](#pipelines-pipeline-argument-constraints){: #pipelines-pipeline-argument-constraints } | `keyword` | `[]` | Constraints to provide to the type when casting the value. For more information, see `Ash.Type`. |
3118-
| [`allow_nil?`](#pipelines-pipeline-argument-allow_nil?){: #pipelines-pipeline-argument-allow_nil? } | `boolean` | `true` | Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised. |
3119-
| [`public?`](#pipelines-pipeline-argument-public?){: #pipelines-pipeline-argument-public? } | `boolean` | `true` | Whether or not the argument should appear in public interfaces |
3120-
| [`sensitive?`](#pipelines-pipeline-argument-sensitive?){: #pipelines-pipeline-argument-sensitive? } | `boolean` | `false` | Whether or not the argument value contains sensitive information, like PII(Personally Identifiable Information). See the [security guide](/documentation/topics/security/sensitive-data.md) for more. |
3121-
| [`default`](#pipelines-pipeline-argument-default){: #pipelines-pipeline-argument-default } | `any` | | The default value for the argument to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value |
3122-
3123-
3124-
3125-
3126-
3127-
### Introspection
3128-
3129-
Target: `Ash.Resource.Actions.Argument`
3130-
31313085
### pipelines.pipeline.change
31323086
```elixir
31333087
change change

lib/ash/resource/dsl.ex

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,9 +1185,6 @@ defmodule Ash.Resource.Dsl do
11851185
target: Ash.Resource.Pipeline,
11861186
schema: Ash.Resource.Pipeline.schema(),
11871187
entities: [
1188-
arguments: [
1189-
@action_argument
1190-
],
11911188
changes: [
11921189
@action_change
11931190
],

lib/ash/resource/pipeline.ex

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ defmodule Ash.Resource.Pipeline do
1010
defstruct [
1111
:name,
1212
:description,
13-
accept: [],
14-
arguments: [],
1513
changes: [],
1614
validations: [],
1715
preparations: [],
@@ -21,8 +19,6 @@ defmodule Ash.Resource.Pipeline do
2119
@type t :: %__MODULE__{
2220
name: atom(),
2321
description: String.t() | nil,
24-
accept: list(atom()) | :*,
25-
arguments: list(),
2622
changes: list(),
2723
validations: list(),
2824
preparations: list(),
@@ -38,11 +34,6 @@ defmodule Ash.Resource.Pipeline do
3834
description: [
3935
type: :string,
4036
doc: "An optional description for the pipeline"
41-
],
42-
accept: [
43-
type: {:or, [{:wrap_list, :atom}, {:literal, :*}]},
44-
default: [],
45-
doc: "A list of attributes to accept. Merged with the action's own accept list."
4637
]
4738
]
4839

lib/ash/resource/transformers/resolve_pipelines.ex

Lines changed: 34 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -24,55 +24,43 @@ defmodule Ash.Resource.Transformers.ResolvePipelines do
2424

2525
dsl_state
2626
|> Transformer.get_entities([:actions])
27-
|> Enum.reduce_while({:ok, dsl_state}, fn action, {:ok, dsl_state} ->
27+
|> Enum.reduce({:ok, dsl_state}, fn action, {:ok, dsl_state} ->
2828
field = entity_field(action.type)
2929
entities = Map.get(action, field, [])
3030

3131
if Enum.any?(entities, &match?(%PipeThrough{}, &1)) do
32-
updated_action = resolve_action(action, field, entities, pipelines, dsl_state)
32+
expanded = resolve_action(action, entities, pipelines, dsl_state)
3333

3434
new_state =
3535
Transformer.replace_entity(
3636
dsl_state,
3737
[:actions],
38-
updated_action,
38+
Map.put(action, field, expanded),
3939
&(&1.name == action.name && &1.type == action.type)
4040
)
4141

42-
{:cont, {:ok, new_state}}
42+
{:ok, new_state}
4343
else
44-
{:cont, {:ok, dsl_state}}
44+
{:ok, dsl_state}
4545
end
4646
end)
4747
end
4848

49-
defp resolve_action(action, field, entities, pipelines, dsl_state) do
50-
{expanded, arguments, accept} =
51-
Enum.reduce(entities, {[], [], []}, fn
52-
%PipeThrough{names: names, where: where}, {expanded, arguments, accept} ->
53-
{new_entities, new_arguments, new_accept} =
54-
expand_pipe_through(names, where, action, pipelines, dsl_state)
49+
defp resolve_action(action, entities, pipelines, dsl_state) do
50+
Enum.flat_map(entities, fn
51+
%PipeThrough{names: names, where: where} ->
52+
expand_pipe_through(names, where, action, pipelines, dsl_state)
5553

56-
{expanded ++ new_entities, arguments ++ new_arguments, accept ++ new_accept}
57-
58-
entity, {expanded, arguments, accept} ->
59-
{expanded ++ [entity], arguments, accept}
60-
end)
61-
62-
action
63-
|> Map.put(field, expanded)
64-
|> merge_arguments(arguments, dsl_state)
65-
|> merge_accept(merge_pipeline_accepts(accept))
54+
entity ->
55+
[entity]
56+
end)
6657
end
6758

6859
defp expand_pipe_through(names, where, action, pipelines, dsl_state) do
69-
Enum.reduce(names, {[], [], []}, fn name, {entities, arguments, accept} ->
60+
Enum.flat_map(names, fn name ->
7061
case Map.fetch(pipelines, name) do
7162
{:ok, pipeline} ->
72-
pipeline_entities = collect_entities(action.type, pipeline, where, dsl_state)
73-
74-
{entities ++ pipeline_entities, arguments ++ pipeline.arguments,
75-
accept ++ List.wrap(if pipeline.accept == :*, do: [:*], else: pipeline.accept)}
63+
collect_entities(action.type, pipeline, where, dsl_state)
7664

7765
:error ->
7866
raise DslError,
@@ -86,135 +74,41 @@ defmodule Ash.Resource.Transformers.ResolvePipelines do
8674

8775
defp collect_entities(type, pipeline, where, dsl_state) do
8876
subject = subject_for_type(type)
89-
entities = source_entities(pipeline, type)
9077

91-
Enum.each(entities, &validate_supports!(&1, subject, pipeline, dsl_state))
92-
93-
Enum.map(entities, fn entity ->
78+
source_entities(pipeline, type)
79+
|> Enum.map(fn entity ->
80+
validate_supports!(entity, subject, pipeline, dsl_state)
9481
Map.update!(entity, :where, &(where ++ &1))
9582
end)
9683
end
9784

98-
defp merge_arguments(action, [], _dsl_state), do: action
99-
100-
defp merge_arguments(action, pipeline_arguments, dsl_state) do
101-
{deduped_pipeline_args, pipeline_conflicts} =
102-
Enum.reduce(pipeline_arguments, {%{}, []}, fn arg, {seen, conflicts} ->
103-
case Map.fetch(seen, arg.name) do
104-
:error ->
105-
{Map.put(seen, arg.name, arg), conflicts}
106-
107-
{:ok, existing} ->
108-
if existing.type == arg.type do
109-
{seen, conflicts}
110-
else
111-
{seen, [{arg.name, existing.type, arg.type} | conflicts]}
112-
end
113-
end
114-
end)
115-
116-
if pipeline_conflicts != [] do
117-
conflict_details =
118-
Enum.map_join(pipeline_conflicts, ", ", fn {name, type1, type2} ->
119-
"`#{name}` (#{inspect(type1)} vs #{inspect(type2)})"
120-
end)
121-
122-
raise DslError,
123-
module: Transformer.get_persisted(dsl_state, :module),
124-
path: [:actions, action.type, action.name],
125-
message: "Pipelines define argument(s) with conflicting types: #{conflict_details}"
126-
end
127-
128-
action_args_by_name = Map.new(action.arguments, &{&1.name, &1})
85+
defp validate_supports!(entity, subject, pipeline, dsl_state) do
86+
case entity_module_and_opts(entity) do
87+
{module, opts} ->
88+
supported = module.supports(opts)
12989

130-
{new_args, action_conflicts} =
131-
Enum.reduce(deduped_pipeline_args, {[], []}, fn {_name, pipeline_arg}, {keep, conflicts} ->
132-
case Map.fetch(action_args_by_name, pipeline_arg.name) do
133-
:error ->
134-
{[pipeline_arg | keep], conflicts}
90+
if subject not in supported do
91+
label = entity.__struct__ |> Module.split() |> List.last()
13592

136-
{:ok, action_arg} ->
137-
if action_arg.type == pipeline_arg.type do
138-
{keep, conflicts}
139-
else
140-
{keep, [pipeline_arg | conflicts]}
141-
end
93+
raise DslError,
94+
module: Transformer.get_persisted(dsl_state, :module),
95+
path: [:pipelines, pipeline.name],
96+
message:
97+
"#{label} `#{inspect(module)}` in pipeline `#{pipeline.name}` does not support `#{inspect(subject)}` (supported: #{inspect(supported)})"
14298
end
143-
end)
14499

145-
if action_conflicts != [] do
146-
conflict_details =
147-
Enum.map_join(action_conflicts, ", ", fn arg ->
148-
action_arg = action_args_by_name[arg.name]
149-
150-
"`#{arg.name}` (pipeline: #{inspect(arg.type)}, action: #{inspect(action_arg.type)})"
151-
end)
152-
153-
raise DslError,
154-
module: Transformer.get_persisted(dsl_state, :module),
155-
path: [:actions, action.type, action.name],
156-
message:
157-
"Action `#{action.name}` redefines pipeline argument(s) with a different type: #{conflict_details}"
158-
end
159-
160-
Map.update!(action, :arguments, &(Enum.reverse(new_args) ++ &1))
161-
end
162-
163-
defp merge_pipeline_accepts(accept_lists) do
164-
if :* in accept_lists do
165-
:*
166-
else
167-
Enum.uniq(accept_lists)
168-
end
169-
end
170-
171-
defp merge_accept(action, []), do: action
172-
defp merge_accept(action, :*), do: Map.put(action, :accept, :*)
173-
174-
defp merge_accept(action, accept) when is_list(accept) do
175-
case Map.get(action, :accept) do
176100
nil ->
177-
Map.put(action, :accept, accept)
178-
179-
:* ->
180-
action
181-
182-
existing when is_list(existing) ->
183-
Map.put(action, :accept, Enum.uniq(accept ++ existing))
101+
:ok
184102
end
185103
end
186104

187-
defp validate_supports!(
188-
%Ash.Resource.Validation{module: module, opts: opts},
189-
subject,
190-
pipeline,
191-
dsl_state
192-
) do
193-
if subject not in module.supports(opts) do
194-
raise DslError,
195-
module: Transformer.get_persisted(dsl_state, :module),
196-
path: [:pipelines, pipeline.name],
197-
message:
198-
"Validation `#{inspect(module)}` in pipeline `#{pipeline.name}` does not support `#{inspect(subject)}` (supported: #{inspect(module.supports(opts))})"
199-
end
200-
end
105+
defp entity_module_and_opts(%Ash.Resource.Validation{module: module, opts: opts}),
106+
do: {module, opts}
201107

202-
defp validate_supports!(
203-
%Ash.Resource.Preparation{preparation: {module, opts}},
204-
subject,
205-
pipeline,
206-
dsl_state
207-
) do
208-
if subject not in module.supports(opts) do
209-
raise DslError,
210-
module: Transformer.get_persisted(dsl_state, :module),
211-
path: [:pipelines, pipeline.name],
212-
message:
213-
"Preparation `#{inspect(module)}` in pipeline `#{pipeline.name}` does not support `#{inspect(subject)}` (supported: #{inspect(module.supports(opts))})"
214-
end
215-
end
108+
defp entity_module_and_opts(%Ash.Resource.Preparation{preparation: {module, opts}}),
109+
do: {module, opts}
216110

217-
defp validate_supports!(_entity, _subject, _pipeline, _dsl_state), do: :ok
111+
defp entity_module_and_opts(_), do: nil
218112

219113
defp source_entities(pipeline, type) when type in [:create, :update, :destroy],
220114
do: pipeline.changes ++ pipeline.validations

0 commit comments

Comments
 (0)