$30 off During Our Annual Pro Sale. View Details »

Optimizing an API for Ember Data

Dan Gebhardt
February 15, 2013

Optimizing an API for Ember Data

Presentation given at Ember Camp 2013.

Dan Gebhardt

February 15, 2013
Tweet

More Decks by Dan Gebhardt

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. Convention
    Configuration
    Saturday, February 16, 13

    View Slide

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

    View Slide

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

    View Slide

  6. Saturday, February 16, 13

    View Slide

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

    View Slide

  8. Ember Data
    In memory store
    Canonical records
    Multi-layered architecture
    Customizable adapters /
    serializers
    Saturday, February 16, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  12. class ApplicationSerializer < ActiveModel::Serializer
    # sideload related data by default
    embed :ids, include: true
    end
    A Sprinkling of Configuration
    Saturday, February 16, 13

    View Slide

  13. Relationships
    source: twitamore.com
    Saturday, February 16, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  22. {
    user: {
    id: 1,
    name: '',
    rights_id: 2
    },
    rights: [{
    id: 2,
    admin: true
    }]
    }
    JSON One-to-None Relationships
    Saturday, February 16, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  29. Embedded
    Relationships
    Creative Commons licensed by: Subhash Chandra
    Saturday, February 16, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  34. Customizations
    Saturday, February 16, 13

    View Slide

  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

    View Slide

  36. Custom Pluralization
    serializer.configure('plurals', {
    hobbit: 'hobbitses'
    });
    Saturday, February 16, 13

    View Slide

  37. {
    post: {
    id: 1,
    titleOfPost: 'Ember is Omakase'
    }
    }
    JSON Custom Keys
    Saturday, February 16, 13

    View Slide

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

    View Slide

  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

    View Slide

  40. Custom Sideloading
    serializer.configure('App.Comment', {
    sideloadAs: 'post_comments'
    });
    Saturday, February 16, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  44. Edge of Convention
    Pagination
    Authentication
    Sparse fieldsets
    Custom includes
    Polymorphism
    Creative Commons licensed by: _chrisUK
    Saturday, February 16, 13

    View Slide

  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

    View Slide