Optimizing an API for Ember Data

E01ec1de2f7783812d2235a6a9aaaeea?s=47 Dan Gebhardt
February 15, 2013

Optimizing an API for Ember Data

Presentation given at Ember Camp 2013.

E01ec1de2f7783812d2235a6a9aaaeea?s=128

Dan Gebhardt

February 15, 2013
Tweet

Transcript

  1. Optimizing An API For Ember Data Dan Gebhardt Saturday, February

    16, 13
  2. Dan Gebhardt @dgeb Saturday, February 16, 13

  3. Convention Configuration Saturday, February 16, 13

  4. “Trivial choices are the enemy” - Yehuda Katz Saturday, February

    16, 13
  5. Ruby on Rails ActiveModel::Serializers Ember.js Ember Data Saturday, February 16,

    13
  6. Saturday, February 16, 13

  7. “What” not “how” DRY Customizable ActiveModel::Serializers Saturday, February 16, 13

  8. Ember Data In memory store Canonical records Multi-layered architecture Customizable

    adapters / serializers Saturday, February 16, 13
  9. underscore_naming include root element id: 1, fk_id: 1, fk_ids: [1]

    conventions for including related data AM::S Conventions Saturday, February 16, 13
  10. DS.RESTAdapter Conventions underscore_naming include root element id: 1, fk_id: 1,

    fk_ids: [1] conventions for including related data Saturday, February 16, 13
  11. DS.RESTAdapter Conventions underscore_naming include root element id: 1, fk_id: 1,

    fk_ids: [1] conventions for including related data IDENTICAL TO ActiveModel::Serializers Saturday, February 16, 13
  12. class ApplicationSerializer < ActiveModel::Serializer # sideload related data by default

    embed :ids, include: true end A Sprinkling of Configuration Saturday, February 16, 13
  13. Relationships source: twitamore.com Saturday, February 16, 13

  14. One-to-Many Relationships App.Post = DS.Model.extend({ title: DS.attr('string'), comments: DS.hasMany('App.Comment') });

    App.Comment = DS.Model.extend({ body: DS.attr('string'), post: DS.belongsTo('App.Post') }); Saturday, February 16, 13
  15. class PostSerializer < ApplicationSerializer attributes :title has_many :comments end class

    CommentSerializer < ApplicationSerializer attributes :body belongs_to :post end One-to-Many Relationships Saturday, February 16, 13
  16. { post: { id: 1, title: 'Ember is Omakase', comment_ids:

    [4, 5, 6] }, comments: [ {id: 4, post_id: 1, body: 'delicious!'}, {id: 5, post_id: 1, body: 'yuno turbolinks?'}, {id: 6, post_id: 1, body: 'is that a tentacle?'} ] } JSON One-to-Many Relationships Saturday, February 16, 13
  17. One-to-One Relationships App.User = DS.Model.extend({ name: DS.attr('string'), rights: DS.belongsTo('App.Rights') });

    App.Rights = DS.Model.extend({ admin: DS.attr('boolean'), user: DS.belongsTo('App.User') }); Saturday, February 16, 13
  18. class UserSerializer < ApplicationSerializer attributes :id, :name has_one :rights end

    class RightsSerializer < ApplicationSerializer attributes :id, :admin belongs_to :user end One-to-One Relationships Saturday, February 16, 13
  19. { user: { id: 1, name: '', rights_id: 2 },

    rights: [{ id: 2, admin: true, user_id: 1 }] } JSON One-to-One Relationships Saturday, February 16, 13
  20. One-to-None Relationships App.User = DS.Model.extend({ name: DS.attr('string'), rights: DS.belongsTo('App.Rights') });

    App.Rights = DS.Model.extend({ admin: DS.attr('boolean') }); Saturday, February 16, 13
  21. class UserSerializer < ApplicationSerializer attributes :id, :name has_one :rights end

    class RightsSerializer < ApplicationSerializer attributes :id, :admin end One-to-None Relationships Saturday, February 16, 13
  22. { user: { id: 1, name: '', rights_id: 2 },

    rights: [{ id: 2, admin: true }] } JSON One-to-None Relationships Saturday, February 16, 13
  23. Many-to-Many Relationships App.Post = DS.Model.extend({ title: DS.attr('string'), body: DS.attr('string'), tags:

    DS.hasMany('App.Tag') }); App.Tag = DS.Model.extend({ name: DS.attr('string'), posts: DS.hasMany('App.Post') }); Saturday, February 16, 13
  24. class PostSerializer < ApplicationSerializer attributes :id, :title, :body has_many :tags

    end class TagSerializer < ApplicationSerializer attributes :id, :name has_many :posts end Many-to-Many Relationships Saturday, February 16, 13
  25. { posts: [ {id: 1, title: 'Hello world', tag_ids: [11,

    12]}, {id: 2, title: 'Goodbye', tag_ids: [11, 13]} ], tags: [ {id: 11, name: 'announcements', post_ids: [1,2]}, {id: 12, name: 'happy', post_ids: [1]}, {id: 13, name: 'sad', post_ids: [2]} ] } JSON Many-to-Many Relationships Saturday, February 16, 13
  26. Many-to-None Relationships App.Post = DS.Model.extend({ title: DS.attr('string'), body: DS.attr('string'), tags:

    DS.hasMany('App.Tag') }); App.Tag = DS.Model.extend({ name: DS.attr('string') }); Saturday, February 16, 13
  27. class PostSerializer < ApplicationSerializer attributes :id, :title, :body has_many :tags

    end class TagSerializer < ApplicationSerializer attributes :id, :name end Many-to-None Relationships Saturday, February 16, 13
  28. { posts: [ {id: 1, title: 'Hello world', tag_ids: [11,

    12]}, {id: 2, title: 'Goodbye', tag_ids: [11, 13]} ], tags: [ {id: 11, name: 'announcements'}, {id: 12, name: 'happy'}, {id: 13, name: 'sad'} ] } JSON Many-to-None Relationships Saturday, February 16, 13
  29. Embedded Relationships Creative Commons licensed by: Subhash Chandra Saturday, February

    16, 13
  30. { post: { id: 1, title: 'Ember is Omakase', comments:

    [ {id: 4, body: 'delicious!'}, {id: 5, body: 'yuno turbolinks?'}, {id: 6, body: 'is that a tentacle?'} ] } } JSON Serialized Embedded Data Saturday, February 16, 13
  31. class PostSerializer < ApplicationSerializer attributes :title has_many :comments, embed: :objects

    end class CommentSerializer < ApplicationSerializer attributes :body belongs_to :post end Embedded Data Serializers Saturday, February 16, 13
  32. Embedded Read-only Data App.Post = DS.Model.extend({ title: DS.attr('string'), comments: DS.hasMany('App.Comment')

    }); App.Comment = DS.Model.extend({ body: DS.attr('string') }); serializer.map('App.Post', { comments: {embedded: 'load'} }); Saturday, February 16, 13
  33. Embedded Writeable Data App.Post = DS.Model.extend({ title: DS.attr('string'), comments: DS.hasMany('App.Comment')

    }); App.Comment = DS.Model.extend({ body: DS.attr('string') }); serializer.map('App.Post', { comments: {embedded: 'always'} }); Saturday, February 16, 13
  34. Customizations Saturday, February 16, 13

  35. { hobbit: {id: 1, name: 'Bilbo'} } { hobbitses: [

    {id: 1, name: 'Bilbo'} {id: 2, name: 'Frodo'} {id: 3, name: 'Samwise'} ] } JSON Custom Pluralization Saturday, February 16, 13
  36. Custom Pluralization serializer.configure('plurals', { hobbit: 'hobbitses' }); Saturday, February 16,

    13
  37. { post: { id: 1, titleOfPost: 'Ember is Omakase' }

    } JSON Custom Keys Saturday, February 16, 13
  38. Custom Keys serializer.map('App.Post', { title: {key: 'titleOfPost'} }); Saturday, February

    16, 13
  39. { post: { id: 1, title: 'Ember is Omakase', comment_ids:

    [4, 5, 6] }, post_comments: [ {id: 4, post_id: 1, body: 'delicious!'}, {id: 5, post_id: 1, body: 'yuno turbolinks?'}, {id: 6, post_id: 1, body: 'is that a tentacle?'} ] } JSON Custom Sideloading Saturday, February 16, 13
  40. Custom Sideloading serializer.configure('App.Comment', { sideloadAs: 'post_comments' }); Saturday, February 16,

    13
  41. Custom Transforms Adapter.registerTransform('excitableString', { serialize: function(value) { return value +

    '!'; }, deserialize: function(value) { return value.substring(0, value.length - 1); } }); App.Greeting = DS.Model.extend({ message: DS.attr('excitableString') }); Saturday, February 16, 13
  42. Custom URLs adapter.set('namespace', 'ember'); person = store.find(Person, 1); // =>

    /ember/people/1 adapter.set('url', 'http://api.ember.dev'); person = store.find(Person, 1); // => http://api.ember.dev/people/1 Saturday, February 16, 13
  43. Bulk Commits adapter.set('bulkCommit', true); store.createRecord(App.Person, {name: 'tomdale'}); store.createRecord(App.Person, {name: 'wycats'});

    store.commit(); // POST to /people // {people: [{name: 'tomdale'}, {name: 'wycats'}]} Saturday, February 16, 13
  44. Edge of Convention Pagination Authentication Sparse fieldsets Custom includes Polymorphism

    Creative Commons licensed by: _chrisUK Saturday, February 16, 13
  45. Resources https://github.com/dgeb/ember_data_example https://github.com/rails-api/active_model_serializers http://stackoverflow.com/questions/tagged/ember-data Saturday, February 16, 13