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

DS.Store & Friends

Eric Kelly
November 13, 2015

DS.Store & Friends

Boston Ember Meetup

How do the different pieces of Ember Data fit together (kind of).

Eric Kelly

November 13, 2015
Tweet

More Decks by Eric Kelly

Other Decks in Programming

Transcript

  1. The Plan • What is the role of DS.Store? •

    What is the role of DS.Adapter? • What is the role of DS.Serializer? • How do these different pieces fit together?
  2. import DS from 'ember-data'; const { Model, attr } =

    DS; export default Model.extend({ name: attr('string'), username: attr('string') }); UserModel
  3. // app/routes/application.js import Ember from 'ember'; const { Route }

    = Ember; export default Route.extend({ model(params) { this.store.findRecord('user', params.userId); } }); ApplicationRoute
  4. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { let record = this._findCachedRecord(modelName, id); if (!record) { record = this._fetchRecord(modelName, id); } return promiseRecord(record); } }); store.findRecord(), kind of
  5. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { let record = this._findCachedRecord(modelName, id); if (!record) { record = this._fetchRecord(modelName, id); } return promiseRecord(record); }, _fetchRecord(modelName, id) { // omitted } }); store.findRecord() When record is not in the cache
  6. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { // omitted }, _fetchRecord(modelName, id) { const url = `/users/${id}`; const promise = this.ajax(url, 'GET').then((payload) => { const record = this.push(payload); return record; }); return promise; } }); store._fetchRecord()
  7. DS.Adapter “In Ember Data, the Adapter determines how data is

    persisted to a backend data store, such as the URL format and headers for a REST API.”
  8. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { // omitted }, _fetchRecord(modelName, id) { const adapter = this.adapterFor(modelName); const promise = adapter.findRecord(modelName, id).then((payload) => { const record = this.push(payload); return record; }); return promise; } }); store.findRecord() When record is not in the cache
  9. // DS.Adapter export default Ember.Object.extend({ findRecord(type, id) { const url

    = this.buildURL(modelName, id, 'findRecord'); return this.ajax(url, 'GET'); }, buildURL(modelName, id, requestType) { switch (requestType) { case 'findRecord': return this.urlForFindRecord(id, modelName); case 'findAll': return this.urlForFindAll(modelName); // pattern continued } } }); DS.Adapter, kind of
  10. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { // omitted }, _fetchRecord(modelName, id) { const adapter = this.adapterFor(modelName); const promise = adapter.findRecord(modelName, id).then((payload) => { const record = this.push(payload); return record; }); return promise; } }); Back to store._fetchRecord()
  11. JSON API Example // JSON API Compliant // GET /users/1

    { “data": { "type": "users", "id": "1", "attributes": { "name": "Eric", "username": "HeroicEric" } } } // Not JSON API Compliant // GET /users/1 { “user": { "id": "1", "name": "Eric", "username": "HeroicEric" } }
  12. DS.Serializer “In Ember Data, serializers format the data sent to

    and received from the backend store. By default, Ember Data serializes data using the JSON API format.”
  13. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { // omitted }, _fetchRecord(modelName, id) { const adapter = this.adapterFor(modelName); const serializer = this.serializerFor(modelName); const promise = adapter.findRecord(modelName, id).then((payload) => { const normalizedPayload = serializer.normalizeResponse( modelName, payload, 'findRecord' ); const record = this.push(normalizedPayload); return record; }); return promise; } }); Back to store._fetchRecord()
  14. // DS.Serializer export default Ember.Object.extend({ normalizeResponse(primaryModelClass, payload, requestType) { switch

    (requestType) { case 'findRecord': return this.normalizeFindRecordResponse(...arguments); case 'findAll': return this.normalizeFindAllResponse(...arguments); // pattern continues } } }); serializer.normalizeResponse()
  15. // DS.Store export default Service.extend({ findRecord(modelName, id, options = {})

    { let record = this._findCachedRecord(modelName, id); if (!record) { record = this._fetchRecord(modelName, id); } return promiseRecord(record); }, _fetchRecord(modelName, id) { const adapter = this.adapterFor(modelName); const serializer = this.serializerFor(modelName); const promise = adapter.findRecord(modelName, id).then((payload) => { const normalizedPayload = serializer.normalizeResponse( modelName, payload, 'findRecord' ); const record = this.push(normalizedPayload); return record; }); return promise; } }); Recap