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.5k
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
670
Worker power!
dgeb
0
450
Modern Ember
dgeb
0
130
The Future of Data in Ember
dgeb
0
400
Give Apps Online Superpowers by Optimizing them for Offline
dgeb
2
180
Overview of Orbit.js
dgeb
0
85
Introducing Ember Engines
dgeb
4
3.4k
Introducing JSON API
dgeb
5
670
Fault Tolerant UX
dgeb
4
900
Other Decks in Programming
See All in Programming
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
ECS Service Connectのこれまでのアップデートと今後のRoadmapを見てみる
tkikuc
2
250
3rd party scriptでもReactを使いたい! Preact + Reactのハイブリッド開発
righttouch
PRO
1
610
Pinia Colada が実現するスマートな非同期処理
naokihaba
4
230
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
Jakarta EE meets AI
ivargrimstad
0
210
どうして僕の作ったクラスが手続き型と言われなきゃいけないんですか
akikogoto
1
120
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.2k
Better Code Design in PHP
afilina
PRO
0
130
Snowflake x dbtで作るセキュアでアジャイルなデータ基盤
tsoshiro
2
520
Hotwire or React? ~アフタートーク・本編に含めなかった話~ / Hotwire or React? after talk
harunatsujita
1
120
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
10
1.3k
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
95
5.2k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
Thoughts on Productivity
jonyablonski
67
4.3k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
Music & Morning Musume
bryan
46
6.2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.7k
Site-Speed That Sticks
csswizardry
0
28
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
0
97
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
42
9.2k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
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