I’m struggling to understand as how my previous implementation (adapters & serializers) able to adopt the new Request Manager, Store & Handlers as in 4.12. By the looks of it, this is also how Ember planning to carry forward - as current documentation (for Adapters & Serializers) shows deprecation warning asking to adopt the new architecture instead.
I always a fan of EmberData and the use of Store methods (findAll, createRecord etc).
Previously, when making requests, I’m able to use REST adapters and Embedded Record serialisers.
The structure also makes sense, where adapters are in one folder while multiple serializers for multiple models are in one folder.
The flow or hierarchy of data also makes sense in “old” architcture.
I’ve been playing around with the new Request Manager and Handler - while the guide is limited and not plenty tutorials available. Here is an example:
/models/todo.js
import Model, { attr, hasMany, belongsTo } from '@ember-data/model';
export default class TodoModel extends Model {
@attr('string') title;
@attr('boolean') completed;
@belongsTo('user') userId;
}
/services/request.js
Using dummy data fetch URL
import RequestManager from '@ember-data/request';
import { CacheHandler } from '@ember-data/store';
import { service } from '@ember/service';
// Custom handler to show how to use a custom fetch implementation.
const RESTHandler = {
async request(context) {
// Build the request URL following Request API.
const response = await fetch('https://jsonplaceholder.typicode.com/todos/', {
method: 'GET'
});
context.setResponse(response);
context.setStream(response.clone().body);
return response.json();
},
};
export default class extends RequestManager {
constructor(createArgs) {
super(createArgs);
// Specify which handler to use to fullfill requests.
this.use([RESTHandler]);
// Specify which cache handler to use to cache responses.
this.useCache(CacheHandler);
}
}
/services/store.js
import Store from '@ember-data/store';
import { service } from '@ember/service';
import Cache from '@ember-data/json-api';
export default class extends Store {
@service('request') requestManager;
createCache(storeWrapper) {
// When is the called? Where do I create my own REST wrapper??
return new Cache(storeWrapper);
}
instantiateRecord(identifier) {
// When is this also called?
console.log(identifier)
}
}
To get data, I use the standard method in /routes/todos.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
export default class TodosRoute extends Route {
@service store;
model() {
return this.store.findAll('todo');
}
}
The request was successful and returned response like so:
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
{
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
}
]
Simple template like this, rendered successfully - using raw response eventhough not in JSON:API spec as Ember usually expects by default.
{{page-title "Todos"}}
<h1>To-do List</h1>
<ol>
{{#each @model as |todo|}}
<li>{{todo.title}}</li>
{{/each}}
</ol>
However, Ember Inspector shows Data blank with no model shown. Do I have to push payload to Store? Normalize? Where do I do this?
When creating record like so;
this.store.createRecord('todo', {
title: 'add a new task to the list',
completed: false,
})
Ember Inspector Data shows no record. When calling save()
, returns error and no network request made.
Couple of questions
- How adapter has been replaced? I assume ‘Handlers’.
- How serializers has been replaced? I assume ‘Cache’.
My case would probably fit this diagram from @ember-data/request:
However, in set up above no Handlers involved?
I would greatly appreciate if someone can help me get my head around this. I will be sharing my ‘before-and-after’ with the hope to help others too.
Sy