This test application implements and showcases a solution for handling REST nested resources (AKA sub-resources).
/resource/:id/sub_resource
It does so with an adapter mixin overriding the buildURL()
method.
Make your sub-resource's adapter extends the mixin.
In the sub-resource's adapter (see example):
[...]
import SubResourceAdapterMixin from '../mixins/sub-resource-adapter';
export default ApplicationAdapter.extend(SubResourceAdapterMixin, {
[...]
});
When using the adapter to query the backend, make sure to provide the
parentResource
.
In a route fetching the index of the sub-resource (see example):
[...]
model() {
let parentResource = this.modelFor('parent-route');
return this.store.findAll('sub-resource', { adapterOptions: { parentResource } });
}
[...]
In a route fetching a single item of the sub-resource (see example):
[...]
model({ id }) {
let parentResource = this.modelFor('parent-route');
return this.store.findRecord('sub-resource', id, { adapterOptions: { parentResource } });
}
[...]
Nested resources are available under the path of a parent resource.
Let's consider the infamous blog example:
- a blog is a collection of
post
s - a
post
hascomment
s - a
comment
has only onepost
A comment
only exists within the context of a post
(well, at least in our dummy blog).
There is the resulting REST API contract:
GET http://localhost:3000/posts
:
[
{
"id": 1,
"title": "Post Title",
"content": "Post content"
}
]
GET http://localhost:3000/posts/1
:
{
"id": 1,
"title": "Post Title",
"content": "Post content"
}
GET http://localhost:3000/posts/1/comments
:
[
{
"id": 1,
"content": "Comment content"
}
]
GET http://localhost:3000/posts/1/comments/1
:
{
"id": 1,
"content": "Comment content"
}
The hard task is to be able to retrieve the
comment
nested-resource.
app/routes/posts/details/comments.js
:
[...]
model() {
return this.store.findAll('comment'); // this won't work, since we need the `post` parent resource to build the URL
}
[...]
The proposed solution overrides the adapter's
buildURL()
method to build the sub-resource URL using the parent resource URL and the sub-resourcepathForType
. Refer to the implementation for more details.
By providing a reference to the parent resource, we are now able to build our sub-resource URL.
app/routes/posts/detail/comments.js
:
[...]
model() {
let post = this.modelFor('posts.detail');
return this.store.findAll('comment', { adapterOptions: { parentResource: post } });
}
[...]
You will need the following things properly installed on your computer.
git clone <repository-url>
this repositorycd nested-resources
yarn install
yarn run json-server --watch mock/db.json --routes mock/routes.json
ember serve --proxy http://localhost:300
- Visit your app at http://localhost:4200.
- Visit your tests at http://localhost:4200/tests.
Make use of the many generators for code, try ember help generate
for more details
yarn run json-server --watch mock/db.json --routes mock/routes.json
ember test --proxy http://localhost:300
ember test --server --proxy http://localhost:300
yarn lint:hbs
yarn lint:js
yarn lint:js --fix
ember build
(development)ember build --environment production
(production)
Specify what it takes to deploy your app.