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/dsls/DSL-AshJsonApi.Resource.md
+23Lines changed: 23 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -132,6 +132,10 @@ A GET route to retrieve a single record
132
132
get :read
133
133
```
134
134
135
+
```
136
+
get :read, path_param_is_composite_key: :id
137
+
```
138
+
135
139
136
140
137
141
### Arguments
@@ -151,6 +155,7 @@ get :read
151
155
|[`name`](#json_api-routes-get-name){: #json_api-routes-get-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
152
156
|[`derive_sort?`](#json_api-routes-get-derive_sort?){: #json_api-routes-get-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
153
157
|[`derive_filter?`](#json_api-routes-get-derive_filter?){: #json_api-routes-get-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
158
+
|[`path_param_is_composite_key`](#json_api-routes-get-path_param_is_composite_key){: #json_api-routes-get-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
154
159
155
160
156
161
@@ -195,6 +200,7 @@ index :read
195
200
|[`name`](#json_api-routes-index-name){: #json_api-routes-index-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
196
201
|[`derive_sort?`](#json_api-routes-index-derive_sort?){: #json_api-routes-index-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
197
202
|[`derive_filter?`](#json_api-routes-index-derive_filter?){: #json_api-routes-index-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
203
+
|[`path_param_is_composite_key`](#json_api-routes-index-path_param_is_composite_key){: #json_api-routes-index-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
198
204
199
205
200
206
@@ -239,6 +245,7 @@ post :create
239
245
|[`name`](#json_api-routes-post-name){: #json_api-routes-post-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
240
246
|[`derive_sort?`](#json_api-routes-post-derive_sort?){: #json_api-routes-post-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
241
247
|[`derive_filter?`](#json_api-routes-post-derive_filter?){: #json_api-routes-post-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
248
+
|[`path_param_is_composite_key`](#json_api-routes-post-path_param_is_composite_key){: #json_api-routes-post-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
242
249
|[`relationship_arguments`](#json_api-routes-post-relationship_arguments){: #json_api-routes-post-relationship_arguments } |`list(atom \| {:id, atom})`|`[]`| Arguments to be used to edit relationships. See the [relationships guide](/documentation/topics/relationships.md) for more. |
243
250
|[`upsert?`](#json_api-routes-post-upsert?){: #json_api-routes-post-upsert? } |`boolean`|`false`| Whether or not to use the `upsert?: true` option when calling `Ash.create/2`. |
244
251
|[`upsert_identity`](#json_api-routes-post-upsert_identity){: #json_api-routes-post-upsert_identity } |`atom`|`false`| Which identity to use for the upsert |
@@ -266,6 +273,10 @@ A PATCH route to update a record
266
273
patch :update
267
274
```
268
275
276
+
```
277
+
patch :update, path_param_is_composite_key: :id
278
+
```
279
+
269
280
270
281
271
282
### Arguments
@@ -288,6 +299,7 @@ patch :update
288
299
|[`name`](#json_api-routes-patch-name){: #json_api-routes-patch-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
289
300
|[`derive_sort?`](#json_api-routes-patch-derive_sort?){: #json_api-routes-patch-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
290
301
|[`derive_filter?`](#json_api-routes-patch-derive_filter?){: #json_api-routes-patch-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
302
+
|[`path_param_is_composite_key`](#json_api-routes-patch-path_param_is_composite_key){: #json_api-routes-patch-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
291
303
292
304
293
305
@@ -312,6 +324,10 @@ A DELETE route to destroy a record
312
324
delete :destroy
313
325
```
314
326
327
+
```
328
+
delete :destroy, path_param_is_composite_key: :id
329
+
```
330
+
315
331
316
332
317
333
### Arguments
@@ -333,6 +349,7 @@ delete :destroy
333
349
|[`name`](#json_api-routes-delete-name){: #json_api-routes-delete-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
334
350
|[`derive_sort?`](#json_api-routes-delete-derive_sort?){: #json_api-routes-delete-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
335
351
|[`derive_filter?`](#json_api-routes-delete-derive_filter?){: #json_api-routes-delete-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
352
+
|[`path_param_is_composite_key`](#json_api-routes-delete-path_param_is_composite_key){: #json_api-routes-delete-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
336
353
337
354
338
355
@@ -378,6 +395,7 @@ related :comments, :read
378
395
|[`name`](#json_api-routes-related-name){: #json_api-routes-related-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
379
396
|[`derive_sort?`](#json_api-routes-related-derive_sort?){: #json_api-routes-related-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
380
397
|[`derive_filter?`](#json_api-routes-related-derive_filter?){: #json_api-routes-related-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
398
+
|[`path_param_is_composite_key`](#json_api-routes-related-path_param_is_composite_key){: #json_api-routes-related-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
381
399
382
400
383
401
@@ -423,6 +441,7 @@ relationship :comments, :read
423
441
|[`name`](#json_api-routes-relationship-name){: #json_api-routes-relationship-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
424
442
|[`derive_sort?`](#json_api-routes-relationship-derive_sort?){: #json_api-routes-relationship-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
425
443
|[`derive_filter?`](#json_api-routes-relationship-derive_filter?){: #json_api-routes-relationship-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
444
+
|[`path_param_is_composite_key`](#json_api-routes-relationship-path_param_is_composite_key){: #json_api-routes-relationship-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
|[`name`](#json_api-routes-post_to_relationship-name){: #json_api-routes-post_to_relationship-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
468
487
|[`derive_sort?`](#json_api-routes-post_to_relationship-derive_sort?){: #json_api-routes-post_to_relationship-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
469
488
|[`derive_filter?`](#json_api-routes-post_to_relationship-derive_filter?){: #json_api-routes-post_to_relationship-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
489
+
|[`path_param_is_composite_key`](#json_api-routes-post_to_relationship-path_param_is_composite_key){: #json_api-routes-post_to_relationship-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
470
490
471
491
472
492
@@ -511,6 +531,7 @@ patch_relationship :comments
511
531
|[`name`](#json_api-routes-patch_relationship-name){: #json_api-routes-patch_relationship-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
512
532
|[`derive_sort?`](#json_api-routes-patch_relationship-derive_sort?){: #json_api-routes-patch_relationship-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
513
533
|[`derive_filter?`](#json_api-routes-patch_relationship-derive_filter?){: #json_api-routes-patch_relationship-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
534
+
|[`path_param_is_composite_key`](#json_api-routes-patch_relationship-path_param_is_composite_key){: #json_api-routes-patch_relationship-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
|[`name`](#json_api-routes-delete_from_relationship-name){: #json_api-routes-delete_from_relationship-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
556
577
|[`derive_sort?`](#json_api-routes-delete_from_relationship-derive_sort?){: #json_api-routes-delete_from_relationship-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
557
578
|[`derive_filter?`](#json_api-routes-delete_from_relationship-derive_filter?){: #json_api-routes-delete_from_relationship-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
579
+
|[`path_param_is_composite_key`](#json_api-routes-delete_from_relationship-path_param_is_composite_key){: #json_api-routes-delete_from_relationship-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
|[`name`](#json_api-routes-route-name){: #json_api-routes-route-name } |`String.t`|| A globally unique name for this route, to be used when generating docs and open api specifications |
602
624
|[`derive_sort?`](#json_api-routes-route-derive_sort?){: #json_api-routes-route-derive_sort? } |`boolean`|`true`| Whether or not to derive a sort parameter based on the sortable fields of the resource |
603
625
|[`derive_filter?`](#json_api-routes-route-derive_filter?){: #json_api-routes-route-derive_filter? } |`boolean`|`true`| Whether or not to derive a filter parameter based on the sortable fields of the resource |
626
+
|[`path_param_is_composite_key`](#json_api-routes-route-path_param_is_composite_key){: #json_api-routes-route-path_param_is_composite_key } |`atom`|| The path parameter that should be parsed as a composite primary key. When specified (e.g., :id), the parameter will be split using the resource's primary key delimiter and mapped to individual primary key fields. This is required for resources with composite primary keys to work correctly with GET, PATCH, and DELETE operations. See the composite primary keys documentation for more details. |
When working with resources that have composite primary keys (multiple fields that together form the unique identifier), AshJsonApi provides special support for encoding and decoding these keys in URLs.
4
+
5
+
## Defining Composite Primary Keys
6
+
7
+
First, define your composite primary key in the JSON API configuration:
delimiter "|"# Use a delimiter that won't conflict with your data
26
+
end
27
+
end
28
+
end
29
+
```
30
+
31
+
### Important Considerations for Delimiters
32
+
33
+
When choosing a delimiter, ensure it won't appear in your actual data:
34
+
35
+
-**UUIDs contain dashes (`-`)** - Don't use `-` as a delimiter if any of your composite key fields are UUIDs
36
+
-**Safe alternatives**: `|`, `~`, `::`, or other characters unlikely to appear in your data
37
+
-**Default delimiter**: If not specified, AshJsonApi uses `-` as the default delimiter
38
+
39
+
## Enabling Composite Key Parsing in Routes
40
+
41
+
To enable automatic parsing of composite primary keys in URL paths, you must opt-in by specifying the `path_param_is_composite_key` option on your routes:
42
+
43
+
```elixir
44
+
json_api do
45
+
type "bio"
46
+
47
+
primary_key do
48
+
keys [:author_id, :category]
49
+
delimiter "|"
50
+
end
51
+
52
+
routes do
53
+
base "/bios"
54
+
55
+
# Enable composite key parsing for the :id parameter
56
+
get :read, path_param_is_composite_key::id
57
+
patch :update, path_param_is_composite_key::id
58
+
delete :destroy, path_param_is_composite_key::id
59
+
60
+
# Other routes that don't need composite key parsing
If you don't specify `path_param_is_composite_key` on a route, the path parameter will be treated as a regular single value, even if your resource has composite primary keys defined. This ensures backward compatibility and prevents unexpected behavior.
115
+
116
+
## Error Handling
117
+
118
+
If the composite key format is invalid (wrong number of parts after splitting), AshJsonApi will return a 404 Not Found error with appropriate JSON:API error formatting.
0 commit comments