Last active
July 29, 2019 19:01
-
-
Save sukima/4af97997693f9082f4c3d56ab480d638 to your computer and use it in GitHub Desktop.
Relationships in ember-data serialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import JSONAPIAdapter from 'ember-data/adapters/json-api'; | |
import { inject as service } from '@ember/service'; | |
const LAST_ID_TAG = '_lastId'; | |
export default JSONAPIAdapter.extend({ | |
storage: service('fake-chrome-store'), | |
debug: service(), | |
generateIdForRecord(store, type) { | |
let lastId = this.storage.get(type, LAST_ID_TAG) || 0; | |
lastId += 1; | |
this.storage.set(type, LAST_ID_TAG, lastId); | |
return `${lastId}`; | |
}, | |
shouldReloadAll() { | |
return false; | |
}, | |
shouldReloadRecord() { | |
return false; | |
}, | |
shouldBackgroundReloadAll() { | |
return false; | |
}, | |
shouldBackgroundReloadRecord() { | |
return false; | |
}, | |
findAll(store, model) { | |
let bucket = this.storage.getBucket(model.modelName); | |
let data = Object.keys(bucket) | |
.filter(key => key !== LAST_ID_TAG) | |
.map(key => bucket[key]); | |
this.debug.log('findAll', model.modelName, JSON.stringify(data, null, 2)); | |
return { data }; | |
}, | |
findRecord(store, type, id) { | |
let data = this.storage.get(type.modelName, id); | |
this.debug.log('findRecord', type.modelName, id, JSON.stringify(data, null, 2)); | |
if (!data) { | |
let error = new Error(`${type.modelName}[${id}] not found`); | |
error.code = 'ENOTFOUND'; | |
throw error; | |
} | |
return { data }; | |
}, | |
createRecord(store, type, snapshot) { | |
let serializedData = this.serialize(snapshot, { includeId: true }); | |
serializedData.data.attributes['created-at'] = new Date().toISOString(); | |
this.debug.log('create', JSON.stringify(serializedData.data, null, 2)); | |
this.storage.set(type.modelName, snapshot.id, serializedData.data); | |
return JSON.parse(JSON.stringify(serializedData)); | |
}, | |
updateRecord(store, type, snapshot) { | |
let serializedData = this.serialize(snapshot, { includeId: true }); | |
this.debug.log('update', JSON.stringify(serializedData.data, null, 2)); | |
this.storage.set(type.modelName, snapshot.id, serializedData.data); | |
return JSON.parse(JSON.stringify(serializedData)); | |
}, | |
deleteRecord(store, type, snapshot) { | |
this.storage.remove(type.modelName, snapshot.id); | |
this.debug.log('delete', type.modelName, snapshot.id); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import { inject as service } from '@ember/service'; | |
import { sort } from '@ember/object/computed'; | |
export default Ember.Controller.extend({ | |
debug: service(), | |
sortBy: ['createdAt:desc'], | |
projects: sort('model', 'sortBy') | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Model from 'ember-data/model'; | |
import attr from 'ember-data/attr'; | |
import { belongsTo, hasMany } from 'ember-data/relationships'; | |
export default Model.extend({ | |
name: attr('string'), | |
createdAt: attr('date'), | |
pullRequests: hasMany('pull-request', { polymorphic: true }) | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import PullRequestModel from './pull-request'; | |
export default PullRequestModel.extend({ | |
polyType: 'Addon' | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import PullRequestModel from './pull-request'; | |
export default PullRequestModel.extend({ | |
polyType: 'Application' | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import PullRequestModel from './pull-request'; | |
export default PullRequestModel.extend({ | |
polyType: 'Misc' | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Model from 'ember-data/model'; | |
import attr from 'ember-data/attr'; | |
import { belongsTo, hasMany } from 'ember-data/relationships'; | |
export default Model.extend({ | |
name: attr('string'), | |
createdAt: attr('date'), | |
project: belongsTo('project', { inverse: 'pullRequests' }) | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
export default Ember.Route.extend({ | |
async beforeModel() { | |
let p = this.store.createRecord('project', { name: 'p2' }); | |
let pr1 = this.store.createRecord('pull-request-misc', { name: 'p2-pr1', project: p }); | |
let pr2 = this.store.createRecord('pull-request-addon', { name: 'p2-pr2', project: p }); | |
let pr3 = this.store.createRecord('pull-request-app', { name: 'p2-pr3', project: p }); | |
await pr1.save(); | |
await pr2.save(); | |
await pr3.save(); | |
await p.save(); | |
await pr1.save(); | |
await pr2.save(); | |
await pr3.save(); | |
}, | |
model() { | |
return this.store.findAll('project', { reload: true }); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import JSONAPISerializer from 'ember-data/serializers/json-api'; | |
export default JSONAPISerializer.extend({ | |
shouldSerializeHasMany() { | |
return true; | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
export default Ember.Service.extend({ | |
init() { | |
this._super(...arguments); | |
this.set('logs', []); | |
}, | |
log() { | |
console.log(...arguments); | |
this.logs.pushObject([...arguments].join(' ')); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Service from '@ember/service'; | |
import { loadFixtureData } from '../utils/fixture-data'; | |
// This is a fake wrapper around what would be a wrapper for Chrome's extension | |
// storage. An real wrapper would be used but have the same API as here. This | |
// one simply allows an adapter to use this API and think it saved to Chome but | |
// really it is just an in-memory version for | |
// development/debugging/demonstration. | |
export default Service.extend({ | |
init() { | |
this._super(...arguments); | |
this._storage = new Map(); | |
loadFixtureData(this._storage); | |
}, | |
getBucket(type) { | |
return this._storage.get(type) || {}; | |
}, | |
get(type, id) { | |
return this.getBucket(type)[id]; | |
}, | |
set(type, id, data) { | |
let bucket = this.getBucket(type); | |
bucket[id] = data; | |
this._storage.set(type, bucket); | |
}, | |
remove(type, id) { | |
let bucket = this.getBucket(type); | |
delete bucket[id]; | |
this._storage.set(type, bucket); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.logs > .log-entry { | |
border-top: thin solid black; | |
padding: 10px; | |
} | |
.logs > .log-entry:first-child { | |
border-top: none; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"version": "0.15.1", | |
"EmberENV": { | |
"FEATURES": {} | |
}, | |
"options": { | |
"use_pods": false, | |
"enable-testing": false | |
}, | |
"dependencies": { | |
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js", | |
"ember": "3.4.3", | |
"ember-template-compiler": "3.4.3", | |
"ember-testing": "3.4.3" | |
}, | |
"addons": { | |
"ember-data": "3.4.2" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function loadFixtureData(storage) { | |
storage.set('pull-request-misc', { | |
_lastId: 1, | |
'1': { | |
id: '1', | |
type: 'pull-request-miscs', | |
attributes: { | |
name: 'p1-pr1', | |
'created-at': '2019-07-29T18:22:40.489Z' | |
} | |
} | |
}); | |
storage.set('pull-request-addon', { | |
_lastId: 1, | |
'1': { | |
id: '1', | |
type: 'pull-request-addons', | |
attributes: { | |
name: 'p1-pr2', | |
'created-at': '2019-07-29T18:22:40.489Z' | |
} | |
} | |
}); | |
storage.set('pull-request-app', { | |
_lastId: 1, | |
'1': { | |
id: '1', | |
type: 'pull-request-apps', | |
attributes: { | |
name: 'p1-pr3', | |
'created-at': '2019-07-29T18:22:40.489Z' | |
} | |
} | |
}); | |
storage.set('project', { | |
_lastId: 1, | |
'1': { | |
id: '1', | |
type: 'projects', | |
attributes: { | |
name: 'p1', | |
'created-at': '2019-07-29T18:22:40.489Z' | |
}, | |
relationships: { | |
'pull-requests': { | |
data: [ | |
{ type: 'pull-request-miscs', id: '1' }, | |
{ type: 'pull-request-addons', id: '1' }, | |
{ type: 'pull-request-apps', id: '1' } | |
] | |
} | |
} | |
} | |
}); | |
console.log(storage); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment