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.6k
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
750
Worker power!
dgeb
0
470
Modern Ember
dgeb
0
140
The Future of Data in Ember
dgeb
0
430
Give Apps Online Superpowers by Optimizing them for Offline
dgeb
2
200
Overview of Orbit.js
dgeb
0
100
Introducing Ember Engines
dgeb
4
3.5k
Introducing JSON API
dgeb
5
710
Fault Tolerant UX
dgeb
4
940
Other Decks in Programming
See All in Programming
Laravel × Clean Architecture
bumptakayuki
PRO
0
130
ASP.NETアプリケーションのモダナイゼーションについて
tomokusaba
0
200
Enterprise Web App. Development (1): Build Tool Training Ver. 5
knakagawa
1
120
The Missing Link in Angular’s Signal Story: Resource API and httpResource
manfredsteyer
PRO
0
110
インプロセスQAにおいて大事にしていること / In-process QA Meetup
medley
0
100
파급효과: From AI to Android Development
l2hyunwoo
0
150
Ruby on Railroad: The Power of Visualizing CFG
ydah
0
270
七輪ライブラリー: Claude AI で作る Next.js アプリ
suneo3476
1
150
Dissecting and Reconstructing Ruby Syntactic Structures
ydah
2
1.4k
On-the-fly Suggestions of Rewriting Method Deprecations
ohbarye
1
4.2k
設計の本質:コード、システム、そして組織へ / The Essence of Design: To Code, Systems, and Organizations
nrslib
10
3.5k
iOSアプリで測る!名古屋駅までの 方向と距離
ryunakayama
0
130
Featured
See All Featured
The Invisible Side of Design
smashingmag
299
50k
It's Worth the Effort
3n
184
28k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
How to Think Like a Performance Engineer
csswizardry
23
1.5k
Code Review Best Practice
trishagee
67
18k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
400
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.7k
Embracing the Ebb and Flow
colly
85
4.7k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Optimizing for Happiness
mojombo
378
70k
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