Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Optimizing an API for Ember Data
Search
Dan Gebhardt
February 15, 2013
Programming
32
4.7k
Optimizing an API for Ember Data
Presentation given at Ember Camp 2013.
Dan Gebhardt
February 15, 2013
Tweet
Share
More Decks by Dan Gebhardt
See All by Dan Gebhardt
An Introduction to the JSON:API Specification
dgeb
5
820
Worker power!
dgeb
0
500
Modern Ember
dgeb
0
160
The Future of Data in Ember
dgeb
0
460
Give Apps Online Superpowers by Optimizing them for Offline
dgeb
2
220
Overview of Orbit.js
dgeb
0
120
Introducing Ember Engines
dgeb
4
3.7k
Introducing JSON API
dgeb
5
740
Fault Tolerant UX
dgeb
4
970
Other Decks in Programming
See All in Programming
「やめとこ」がなくなった — 1月にZennを始めて22本書いた AI共創開発のリアル
atani14
0
350
CSC307 Lecture 14
javiergs
PRO
0
450
Rubyと楽しいをつくる / Creating joy with Ruby
chobishiba
0
200
API Platformを活用したPHPによる本格的なWeb API開発 / api-platform-book-intro
ttskch
1
120
Geminiの機能を調べ尽くしてみた
naruyoshimi
0
200
Python’s True Superpower
hynek
0
200
grapheme_strrev関数が採択されました(あと雑感)
youkidearitai
PRO
1
210
RubyとGoでゼロから作る証券システム: 高信頼性が求められるシステムのコードの外側にある設計と運用のリアル
free_world21
0
210
文字コードの話
qnighy
43
17k
Rails Girls Tokyo 18th GMO Pepabo Sponsor Talk
yutokyokutyo
0
200
株式会社 Sun terras カンパニーデック
sunterras
0
2k
AI活用のコスパを最大化する方法
ochtum
0
120
Featured
See All Featured
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
140
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.4k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.1k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
How STYLIGHT went responsive
nonsquared
100
6k
Mind Mapping
helmedeiros
PRO
1
110
The Limits of Empathy - UXLibs8
cassininazir
1
240
Building a Modern Day E-commerce SEO Strategy
aleyda
45
8.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
130
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Transcript
Optimizing An API For Ember Data Dan Gebhardt Saturday, February
16, 13
Dan Gebhardt @dgeb Saturday, February 16, 13
Convention Configuration Saturday, February 16, 13
“Trivial choices are the enemy” - Yehuda Katz Saturday, February
16, 13
Ruby on Rails ActiveModel::Serializers Ember.js Ember Data Saturday, February 16,
13
Saturday, February 16, 13
“What” not “how” DRY Customizable ActiveModel::Serializers Saturday, February 16, 13
Ember Data In memory store Canonical records Multi-layered architecture Customizable
adapters / serializers Saturday, February 16, 13
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
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
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
class ApplicationSerializer < ActiveModel::Serializer # sideload related data by default
embed :ids, include: true end A Sprinkling of Configuration Saturday, February 16, 13
Relationships source: twitamore.com Saturday, February 16, 13
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
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
{ 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
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
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
{ user: { id: 1, name: '', rights_id: 2 },
rights: [{ id: 2, admin: true, user_id: 1 }] } JSON One-to-One Relationships Saturday, February 16, 13
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
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
{ user: { id: 1, name: '', rights_id: 2 },
rights: [{ id: 2, admin: true }] } JSON One-to-None Relationships Saturday, February 16, 13
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
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
{ 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
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
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
{ 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
Embedded Relationships Creative Commons licensed by: Subhash Chandra Saturday, February
16, 13
{ 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
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
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
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
Customizations Saturday, February 16, 13
{ 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
Custom Pluralization serializer.configure('plurals', { hobbit: 'hobbitses' }); Saturday, February 16,
13
{ post: { id: 1, titleOfPost: 'Ember is Omakase' }
} JSON Custom Keys Saturday, February 16, 13
Custom Keys serializer.map('App.Post', { title: {key: 'titleOfPost'} }); Saturday, February
16, 13
{ 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
Custom Sideloading serializer.configure('App.Comment', { sideloadAs: 'post_comments' }); Saturday, February 16,
13
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
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
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
Edge of Convention Pagination Authentication Sparse fieldsets Custom includes Polymorphism
Creative Commons licensed by: _chrisUK Saturday, February 16, 13
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