You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: documentation/topics/actions/actions.md
+109Lines changed: 109 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -239,6 +239,115 @@ Ticket
239
239
240
240
That is the best of both worlds! These same lessons transfer to all action types (changeset-based, query-based, and generic actions) as well.
241
241
242
+
## Pipelines
243
+
244
+
Pipelines let you define reusable groups of changes, validations, and preparations that can be shared across multiple actions. Instead of duplicating the same logic in every action, you define it once in a `pipeline` and reference it with `pipe_through`.
245
+
246
+
### Defining Pipelines
247
+
248
+
Pipelines are declared in a top-level `pipelines` block on the resource. Each pipeline can contain `change`, `validate`, and `prepare` declarations, just like an action.
249
+
250
+
```elixir
251
+
pipelines do
252
+
pipeline :auditeddo
253
+
change set_attribute(:updated_by, actor(:id))
254
+
validate present(:updated_by)
255
+
end
256
+
257
+
pipeline :sorted_by_namedo
258
+
prepare build(sort: [:name])
259
+
end
260
+
end
261
+
```
262
+
263
+
### Using Pipelines in Actions
264
+
265
+
Reference pipelines from any action using `pipe_through`:
266
+
267
+
```elixir
268
+
actions do
269
+
create :createdo
270
+
accept [:name, :email]
271
+
pipe_through [:audited]
272
+
end
273
+
274
+
update :updatedo
275
+
accept [:name, :email]
276
+
pipe_through [:audited]
277
+
end
278
+
279
+
read :listdo
280
+
pipe_through [:sorted_by_name]
281
+
end
282
+
end
283
+
```
284
+
285
+
The pipeline's entities are expanded inline at compile time — the action behaves exactly as if you had written the changes, validations, and preparations directly.
286
+
287
+
### How Entity Types Are Resolved
288
+
289
+
Pipelines can contain changes, validations, and preparations, but not all of these apply to every action type:
290
+
291
+
-**Create, Update, Destroy actions** receive the pipeline's `change` and `validate` entities. Preparations are ignored.
292
+
-**Read and Generic actions** receive the pipeline's `prepare` and `validate` entities. Changes are ignored.
293
+
294
+
This means you can define a pipeline with all three entity types and safely reference it from any action type — only the applicable entities will be included.
295
+
296
+
### Ordering
297
+
298
+
Pipeline entities are inserted **at the position of the `pipe_through` declaration** within the action. This gives you full control over ordering:
299
+
300
+
```elixir
301
+
create :createdo
302
+
accept [:name]
303
+
change set_attribute(:state, :before) # runs first
304
+
pipe_through [:my_pipeline] # pipeline entities run second
305
+
change set_attribute(:name, "after") # runs third
306
+
end
307
+
```
308
+
309
+
When referencing multiple pipelines in a single `pipe_through`, their entities are appended in the order listed:
310
+
311
+
```elixir
312
+
pipe_through [:pipeline_a, :pipeline_b]
313
+
# pipeline_a entities first, then pipeline_b entities
314
+
```
315
+
316
+
You can also use multiple `pipe_through` declarations in the same action:
317
+
318
+
```elixir
319
+
create :createdo
320
+
pipe_through [:audit]
321
+
pipe_through [:guard], where:present(:name)
322
+
accept [:name]
323
+
end
324
+
```
325
+
326
+
### Conditional Pipelines with `where`
327
+
328
+
You can make a pipeline's entities conditional using the `where` option on `pipe_through`. The `where` conditions are prepended to each entity's existing `where` conditions:
0 commit comments