Skip to content

Commit 2cce6ab

Browse files
authored
docs: Enhance relationships documentation clarity and accuracy (#355)
1 parent 60a4fda commit 2cce6ab

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

documentation/topics/relationships.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,101 @@ Non-map argument types, e.g `argument :author, :integer` (expecting an author id
7373
JSON:API, because it expects `{"type": _type, "id" => id}` for relationship values. To support non-map arguments in `relationship_arguments`,
7474
instead of `:author`, use `{:id, :author}`. This works for `{:array, _}` type arguments as well, so the value would be a list of ids.
7575

76+
77+
## Creating related resources without the id
78+
79+
This feature is useful for creating relationships without requiring two separate API calls and without needing to associate resources with an ID first. This is an escape hatch from the standard approach and is not JSON:API spec compliant, but it is completely possible to implement.
80+
81+
```elixir
82+
# With a post route that references the `leads` argument, this will mean that
83+
# locations will have the ability to create Lead resources when called from
84+
# the API
85+
json_api do
86+
routes do
87+
base_route "/location", Marketplace.Location do
88+
post :create, relationship_arguments: [:leads]
89+
end
90+
91+
base_route "/lead", Marketplace.Lead do
92+
post :create
93+
end
94+
end
95+
end
96+
97+
98+
# In the leads resource you will have the following:
99+
actions do
100+
create :create do
101+
primary?(true)
102+
accept([:type, :description, :priority, :location_id])
103+
end
104+
end
105+
106+
relationships do
107+
belongs_to :location, Marketplace.Location
108+
end
109+
110+
# In the Location resource you will have the following:
111+
112+
actions do
113+
create :create do
114+
primary?(true)
115+
accept([:name, :location, :images])
116+
argument(:leads, {:array, :map}, allow_nil?: false)
117+
118+
change(manage_relationship(:leads, type: :create))
119+
end
120+
end
121+
122+
123+
relationships do
124+
has_many :leads, Marketplace.Lead
125+
end
126+
```
127+
128+
This way, when requesting to create a location, leads will be automatically created as well.
129+
130+
```json
131+
{
132+
"data": {
133+
"type": "location",
134+
"attributes": {
135+
"name": "Test Location",
136+
"location": {
137+
"lat": 32323,
138+
"long": 23232,
139+
"address": "test street 123"
140+
},
141+
"images": ["url1", "url2", "url3"]
142+
},
143+
"relationships": {
144+
"leads": {
145+
"data": [
146+
{
147+
"type": "lead",
148+
"meta": {
149+
"type": "Roof",
150+
"description": "roofing has 3 holes to fix",
151+
"priority": "high"
152+
}
153+
},
154+
{
155+
"type": "lead",
156+
"meta": {
157+
"type": "garden",
158+
"description": "Garden looks like it could be polished",
159+
"priority": "medium"
160+
}
161+
}
162+
]
163+
}
164+
}
165+
}
166+
}
167+
```
168+
169+
Note that the related data won't be returned unless included with the include query parameter. For the JSON:API specification on the include parameter, see [json api fetching includes](https://jsonapi.org/format/#fetching-includes).
170+
76171
## Relationship Manipulation Routes
77172

78173
You can also specify routes that are dedicated to manipulating relationships. We generally suggest the above approach, but JSON:API spec also allows for dedicated relationship routes. For example:

0 commit comments

Comments
 (0)