Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Ember Data 2.0

Introduction to Ember Data 2.0

A basic introduction to Ember Data 2.0 with a couple of deep dives in customizing adapters and serializers.

Christoffer Persson

October 24, 2015
Tweet

Other Decks in Programming

Transcript

  1. DEFINING MODELS export default DS.Model.extend({ // models/user.js firstName: DS.attr(), lastName:

    DS.attr(), age: DS.attr(), isAdmin: DS.attr(), company: DS.belongsTo() }); export default DS.Model.extend({ // models/company.js name: DS.attr(), users: DS.hasMany() });
  2. DEFINING MODELS export default DS.Model.extend({ // models/user.js firstName: DS.attr(), lastName:

    DS.attr(), age: DS.attr(), isAdmin: DS.attr(), company: DS.belongsTo('company') }); export default DS.Model.extend({ // models/company.js name: DS.attr(), users: DS.hasMany('user') });
  3. DEFINING MODELS export default DS.Model.extend({ // models/regular-user.js firstName: DS.attr(), lastName:

    DS.attr(), age: DS.attr(), isAdmin: DS.attr(), company: DS.belongsTo('company') }); export default DS.Model.extend({ // models/company.js name: DS.attr(), users: DS.hasMany('regular-user') });
  4. DEFINING MODELS export default DS.Model.extend({ // models/regular-user.js firstName: DS.attr(), lastName:

    DS.attr(), age: DS.attr(), isAdmin: DS.attr(), company: DS.belongsTo('company') }); export default DS.Model.extend({ // models/company.js name: DS.attr(), users: DS.hasMany('regular-user') });
  5. DEFINING MODELS export default DS.Model.extend({ // models/regular-user.js firstName: DS.attr(), lastName:

    DS.attr(), age: DS.attr(), isAdmin: DS.attr({ defaultValue: false }), company: DS.belongsTo('company') }); export default DS.Model.extend({ // models/company.js name: DS.attr(), users: DS.hasMany('regular-user') });
  6. DEFINING MODELS export default DS.Model.extend({ // models/regular-user.js firstName: DS.attr('string'), lastName:

    DS.attr('string'), age: DS.attr('number'), isAdmin: DS.attr('boolean', { defaultValue: false }), company: DS.belongsTo('company') }); export default DS.Model.extend({ // models/company.js name: DS.attr('string'), users: DS.hasMany('regular-user') });
  7. CUSTOM TRANSFORM // transforms/temperature.js export default DS.Transform.extend({ deserialize(value) { return

    (value * 1.8) + 32; }, serialize(value) { return (value - 32) / 1.8; } });
  8. FINDING DATA USING THE STORE // GET /posts store.findAll('post').then((posts) =>

    { // ... }); // GET /posts/1 store.findRecord('post', 1).then((post) => { // ... });
  9. DEFAULT RELOADING IN EMBER DATA 2.0 findAll(type) ▸ If no

    records with matching type are present in the store, fetch and wait for promise to resolve. ▸ If there's at least one record already in the store, resolve immediately and schedule a background reload.
  10. DEFAULT RELOADING IN EMBER DATA 2.0 findRecord(type, id) ▸ If

    no record with matching type and id is present in the store, fetch and wait for promise to resolve. ▸ If a record is already in the store, return immediately and schedule a background reload.
  11. FORCE FRESH DATA // GET /posts store.findAll('post', { reload: true

    }).then((posts) => { // ... }); // GET /posts/1 store.findRecord('post', 1, { reload: true }).then((post) => { // ... });
  12. QUERYING DATA USING THE STORE // GET /posts?published=true store.query('post', {

    published: true }).then((posts) => { // ... }); // GET /posts?slug=fantastic-ember store.queryRecord('post', { slug: 'fantastic-ember' }).then((post) => { // ... });
  13. PUSHING DATA INTO THE STORE You can push a JSON

    API Document to the store. store.push({ data: { type: 'post', id: '1', attributes: { title: 'Ember is Fantastic' } } });
  14. EMBER DATA INTERNAL JSON API FORMAT ▸ Use camelCase for

    attributes and relationships ▸ Use singular dash-case types
  15. AVAILABLE ADAPTER METHODS ▸ findAll(store, type, sinceToken) ▸ findBelongsTo(store, snapshot,

    url) ▸ findHasMany(store, snapshot, url) ▸ findRecord(store, type, id, snapshot)
  16. AVAILABLE ADAPTER METHODS ▸ findMany(store, type, ids, snapshots) export default

    DS.JSONAPIAdapter.extend({ coalesceFindRequests: true });
  17. CUSTOM URLS ▸ urlForFindAll(modelName) ▸ urlForFindBelongTo(id, modelName) ▸ urlForFindHasMany(id, modelName)

    ▸ urlForFindMany(ids, modelName, snapshots) ▸ urlForFindRecord(id, modelName, snapshot)
  18. CUSTOM URLS ▸ pathForType(modelName) // adapters/application.js export default DS.JSONAPIAdapter.extend({ pathForType(modelName)

    { // Change the default `/line-items` to `/LINE-ITEMS` return this._super(modelName).toUpperCase(); } });
  19. CHANGE THE RELOAD BEHAVIOR ▸ shouldReloadAll(store, snapshotArray) ▸ shouldReloadRecord(store, snapshot)

    ▸ shouldBackgroundReloadAll(store, snapshotArray) ▸ shouldBackgroundReloadRecord(store, snapshot)
  20. NORMALIZE DATA Ember data provides two primary entry points to

    normalize your data: ▸ normalizeResponse(store, primaryModelClass, payload, id, requestType) ▸ normalize(modelClass, resourceHash)
  21. EMBER DATA EXPECTS A JSON API DOCUMENT If you inherit

    from any of the built-in serializers, make sure you always call _super().
  22. NORMALIZE A FULL RESPONSE PAYLOAD normalizeResponse(store, primaryModelClass, payload, id, requestType)

    { // { // status: 'ok', // response: { // ... // } // } payload = payload.response; return this._super(payload); }
  23. NORMALIZE A SINGLE RESOURCE normalize(modelClass, resourceHash) { // { //

    _id: 1, // _title: 'This is my title' // } resourceHash.id = resourceHash._id; resourceHash.title = resourceHash._title; delete resourceHash._id; delete resourceHash._title; return this._super(modelClass, resourceHash); }
  24. THE SERIALIZER NORMALIZATION FLOW !" normalizeFindAllResponse() """""# $" normalizeFindHasManyResponse() "%"

    normalizeArrayResponse() """""""""""""""""""""""""""""""# $" normalizeFindManyResponse() """"& ' $" normalizeQueryResponse() """""""( ' ' ' $" normalizeFindRecordResponse() """""""""""""""""""""""""""""""# ' normalizeResponse() "%" normalizeFindBelongsToResponse() """"""""""""""""""""""""""""& ' $" normalizeQueryRecordResponse() """"""""""""""""""""""""""""""& ' ' ' ' $" normalizeCreateRecordResponse() "# ' ' $" normalizeDeleteRecordResponse() "%" normalizeSaveResponse() ")" normalizeSingleResponse() ")" normalize() *" normalizeUpdateRecordResponse() "(
  25. NORMALIZE A SINGLE RESOURCE normalize(modelClass, resourceHash) { // { //

    _id: 1, // _title: 'This is my title', // _author: 1 // } resourceHash.id = resourceHash._id; resourceHash.title = resourceHash._title; delete resourceHash._id; delete resourceHash._title; return this._super(modelClass, resourceHash); }
  26. NORMALIZE A SINGLE RESOURCE ALTERNATIVES keyForAttribute(key, method) { key =

    this._super(key, method); return `_${key}`; } keyForRelationship(key, modelClass, method) { key = this._super(key, method); return `_${key}`; }
  27. ACCESSING INFORMATION IN A SNAPSHOT Getting unloaded relationships will not

    trigger a fetch. snapshot.id; snapshot.modelName; snapshot.attr('title'); snapshot.belongsTo('author'); snapshot.hasMany('comments');