Slide 1

Slide 1 text

Introduction to  ember-data 12/18/2013, Ember.BP

Slide 2

Slide 2 text

A data persistence library for Ember.js

Slide 3

Slide 3 text

App.Store = DS.Store.extend({! revision: 12,! adapter: App.WonkyAdapter.create! })!

Slide 4

Slide 4 text

App.Adapter = App.WonkyAdapter!

Slide 5

Slide 5 text

History • The “revision” have become a bit unwieldy • Big revamp (aka. jj-abrams branch) in August • Much slimmer code-base • currently 1.0.0.beta-3

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

What does it do? • Maps back-end data <=> front-end records • Abstracts away common back-end <=> front-end communication patterns • Manages store of client-side records • Deals with relationships between models

Slide 8

Slide 8 text

Do I need it? • Discourse does not use it, so ... • It can greatly reduce boilerplate code • Gives you nice features • http://balinterdi.com/2013/12/03/roll-your- own-ember-dot-js-identity-map.html

Slide 9

Slide 9 text

Does it fit my needs? • Assumes “sane” REST API defaults • Assumes certain payload structure • Has fine-grained hooks to modify defaults • Extend via adapters to connect to different backends (e.g localstorage, Firebase)

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

210K ember-data-1.0.0-beta.3.js 60K ember-data.min.js 204K ember-data.prod.js

Slide 12

Slide 12 text

REST Adapter

Slide 13

Slide 13 text

Fetching all records • this.store.find(‘artist’) • => GET /artists • Assumes a root ‘artists’ key in response

Slide 14

Slide 14 text

Finding a record by id • this.store.find(‘artist’, 24) • => GET /artists/24 • Assumes a root ‘artist’ key in response

Slide 15

Slide 15 text

Querying records • this.store.find(‘artist’, { award: ‘grammy’ }) • => GET /artists?award=grammy • Assumes a root ‘artists’ key in response

Slide 16

Slide 16 text

Saving a new record • a = this.store.createRecord(‘artist’) • a.save().then(...) • => POST /artists • with the record’s jsonified attributes as payload

Slide 17

Slide 17 text

Saving an existing record • a = this.get(‘model’) • a.save().then(...) • => PUT /artists/42 • with the record’s jsonified attributes as payload

Slide 18

Slide 18 text

Deleting a record • this.get(‘model’).deleteRecord() • this.get(‘model’).save() • => DELETE /artists/42

Slide 19

Slide 19 text

Customization • namespace: ‘/api/v1’ • host: ‘api.google.com’ • this.store.find(‘artists’) • => GET ‘http://api.google.com/v1/artists

Slide 20

Slide 20 text

The Promised Land • All find and save calls returns promises • Makes all kinds of patterns possible

Slide 21

Slide 21 text

Retry person.save().then(null, function() {! return person.save();! }).then(function() {! });!

Slide 22

Slide 22 text

Find or create this.store.find('artist', 24).then(null, function() {! this.store.createRecord('artist');! });!

Slide 23

Slide 23 text

The golden response

Slide 24

Slide 24 text

{! "artists": [! {! "id": 1,! "name": "Pearl Jam",! "songs": [1, 2, 3, 4, 5, 6]! },! (...)! ],! "songs": [! {! "id": 1,! "title": "Yellow Ledbetter",! "rating": 5! },! {! "id": 2,! "title": "Daughter",! "rating": 5! },! {! "id": 3,! "title": "Animal",! "rating": 4! },! (...)! ]! }!

Slide 25

Slide 25 text

Deserialization hooks

Slide 26

Slide 26 text

extractSingle, extractArray • When the top-level key is not what it should be (or missing) {! "id": 1,! "name": "Pearl Jam",! "songs": [1, 2, 3, 4, 5, 6]! }!

Slide 27

Slide 27 text

normalize • When all the attributes are “wrong” the same way "artists": [! {! "_id": 1,! "name": "Pearl Jam",! },! ],! "songs": [! {! "_id": 1,! "title": "Yellow Ledbetter",! },! ]!

Slide 28

Slide 28 text

normalizeHash • When attributes are “wrong” in different ways, depending on type "artists": [! {! "_id": 1,! "name": "Pearl Jam",! },! ],! "songs": [! {! "ID": 1,! "TITLE": "Yellow Ledbetter",! },! ]!

Slide 29

Slide 29 text

Naming conventions • hasMany relationship keys match the relationship name (songs, not song_ids) • composed names are camelCased, not underscored (firstName, not first_name) • DS.ActiveModelSerializer to work with the ActiveModelSerializer in the Rails API

Slide 30

Slide 30 text

Serialization hooks

Slide 31

Slide 31 text

serializeIntoHash • when the root key is not what the server expects • { blogPosts: [...] } => { blog_posts: [...] }

Slide 32

Slide 32 text

serializeAttribute • when the attribute keys are not correct • { user: { firstName: ... } => { user: { first_name: ... }

Slide 33

Slide 33 text

App.Artist = DS.Model.extend({! name: DS.attr('string'),! born: DS.attr('date'),! yearsActive: DS.attr('number'),! popular: DS.attr('boolean',! { defaultValue: false }),! works: DS.hasMany()! });! Model definition

Slide 34

Slide 34 text

Bonus feature

Slide 35

Slide 35 text

Érdi Bálint @baaz http://emberjs.balinterdi.com