Created
September 10, 2015 01:48
-
-
Save 2468ben/dde2d551a93509b99deb to your computer and use it in GitHub Desktop.
Active Model Sideload-only Serializer code
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
//mirage/config.js | |
import Em from 'ember'; | |
import utils from 'ember-cli-mirage/shorthands/utils'; | |
import serializerDefs from 'crowdly-pa/tests/helpers/serializer-defs'; | |
import SerializerMachine from 'crowdly-pa/tests/helpers/serializer-machine'; | |
import { pluralize } from 'ember-inflector'; | |
export default function() { | |
this.timing = 50; // delay for each request, automatically set to 0 during testing | |
} | |
// You can optionally export a config that is only loaded during tests | |
export function testConfig() { | |
this.logging = true; | |
//Custom Serializer Machine | |
const sM = new SerializerMachine(server.db, serializerDefs); | |
server.sM = sM; | |
this.get('/me', (db, request) => { | |
const _me = db.users.find(1); | |
return sM.serializeRecords('user', _me, request); | |
}); | |
} |
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
//tests/helpers/mock-serializer.js | |
import extend from 'ember-cli-mirage/utils/extend'; | |
class MockSerializer { | |
constructor() { | |
this.relationships.forEach((rel) => { | |
if(!rel.key) { rel.key = rel.type; } | |
if(!rel.inverseOf) { rel.inverseOf = this.type; } | |
const idSuffix = rel.assoc === 'belongsTo' ? '_id' : '_ids'; | |
rel.fk = `${rel.key}${idSuffix}`; | |
}); | |
} | |
serialize(record, request) { | |
return record; | |
} | |
relationshipsFor(record, request) { | |
return []; | |
} | |
relsByKey(keys = []) { | |
return keys.map((key) => this.relationships.findBy('key', key)); | |
} | |
} | |
MockSerializer.prototype.relationships = []; | |
MockSerializer.prototype.type = null; | |
MockSerializer.extend = extend; | |
export default MockSerializer; |
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
//tests/helpers/serializer-defs.js | |
import Em from 'ember'; | |
import utils from 'ember-cli-mirage/shorthands/utils'; | |
const serializerDefs = [ | |
{ | |
type: 'user', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'partner' | |
},{ | |
assoc: 'hasMany', | |
type: 'bucket_membership' | |
},{ | |
assoc: 'hasMany', | |
type: 'topic' | |
},{ | |
assoc: 'hasMany', | |
type: 'comment' | |
}], | |
relationshipsFor: function(record, request) { | |
const _qps = request.queryParams; | |
const _keys = ['bucket_membership']; | |
if(_qps.include_partner) { _keys.addObject('partner'); } | |
return this.relsByKey(_keys); | |
}, | |
serialize: function(record, request) { | |
const _qps = request.queryParams; | |
const attrs = Em.copy(record); | |
if(!_qps.include_interaction_counts) { | |
delete attrs.likes_count; | |
delete attrs.comments_count; | |
delete attrs.shares_count; | |
} else if(_qps.is_reviewer) { | |
delete attrs.shares_count; | |
} | |
return attrs; | |
} | |
},{ | |
type: 'partner', | |
relationships: [{ | |
assoc: 'hasMany', | |
type: 'bucket' | |
},{ | |
assoc: 'hasMany', | |
type: 'landing_page' | |
},{ | |
assoc: 'hasMany', | |
type: 'external_link' | |
}], | |
relationshipsFor: function(record, request) { | |
return this.relsByKey(['bucket','landing_page','external_link']); | |
} | |
},{ | |
type: 'landing_page', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'partner' | |
},{ | |
assoc: 'belongsTo', | |
type: 'bucket' | |
}] | |
}, | |
{ | |
type: 'external_link', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'partner' | |
}], | |
serialize: function(record, request) { | |
const attrs = Em.copy(record); | |
if(!attrs.exclude_details) { | |
delete attrs.global_clicks; | |
delete attrs.shortened_clink_url; | |
} | |
return attrs; | |
} | |
},{ | |
type: 'keyword', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'user' | |
}] | |
},{ | |
type: 'bucket', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'partner' | |
},{ | |
assoc: 'hasMany', | |
type: 'bucket_memberships' | |
},{ | |
assoc: 'belongsTo', | |
type: 'landing_page' | |
}] | |
},{ | |
type: 'bucket_membership', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'partner' | |
},{ | |
assoc: 'belongsTo', | |
type: 'bucket' | |
},{ | |
assoc: 'belongsTo', | |
type: 'user' | |
},{ | |
assoc: 'belongsTo', | |
type: null, | |
key: 'external', | |
polymorphic: true | |
}] | |
},{ | |
type: 'like', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: null, | |
key: 'subject', | |
inverseOf: 'partner_like', | |
polymorphic: true | |
}] | |
},{ | |
type: 'topic', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'user' | |
},{ | |
assoc: 'belongsTo', | |
type: 'like', | |
key: 'partner_like', | |
inverseOf: 'subject' | |
},{ | |
assoc: 'hasMany', | |
type: 'comment', | |
key: 'response', | |
inverseOf: 'subject' | |
},{ | |
assoc: 'hasMany', | |
type: 'bucket_membership' | |
}], | |
serialize: function(record, request) { | |
const _qps = request.queryParams; | |
const attrs = Em.copy(record); | |
if(_qps.exclude_response_ids) { | |
delete attrs.response_ids; | |
} else if(attrs.response_ids) { | |
attrs.responses_count = attrs.response_ids.length; | |
} | |
return attrs; | |
}, | |
relationshipsFor: function(record, request) { | |
return this.relsByKey(['user','partner_like','response']); | |
}, | |
},{ | |
type: 'comment', | |
relationships: [{ | |
assoc: 'belongsTo', | |
type: 'user' | |
},{ | |
assoc: 'belongsTo', | |
type: 'like', | |
key: 'partner_like' | |
},{ | |
assoc: 'belongsTo', | |
type: 'topic', | |
key: 'subject', | |
inverseOf: 'response' | |
},{ | |
assoc: 'belongsTo', | |
type: 'comment', | |
key: 'parent', | |
inverseOf: 'response' | |
},{ | |
assoc: 'hasMany', | |
type: 'comment', | |
key: 'response', | |
inverseOf: 'parent' | |
},{ | |
assoc: 'hasMany', | |
type: 'bucket_membership' | |
}], | |
relationshipsFor: function(record, request) { | |
return this.relsByKey(['user','partner_like','response']); | |
}, | |
serialize: function(record, request) { | |
const _qps = request.queryParams; | |
const attrs = Em.copy(record); | |
if(_qps.exclude_response_ids) { | |
delete attrs.response_ids; | |
} else if(attrs.response_ids) { | |
attrs.responses_count = attrs.response_ids.length; | |
} | |
attrs.replyable = attrs.subject_id || attrs.parent_id; | |
return attrs; | |
} | |
} | |
]; | |
export default serializerDefs; |
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
//tests/helpers/serializer-machine.js | |
import Em from 'ember'; | |
import { pluralize } from 'ember-inflector'; | |
import MockSerializer from './mock-serializer'; | |
class SerializerMachine { | |
constructor(db, defs) { | |
this.db = db; | |
this.setupSerializers(defs); | |
} | |
setupSerializers(defs) { | |
this.mockSerializers = {}; | |
defs.forEach((def) => { | |
const _serializer = new (MockSerializer.extend(def))(); | |
this.mockSerializers[_serializer.type] = _serializer; | |
}); | |
} | |
addCollectionToResponse(response, collection) { | |
collection.forEach((recordsHash) => { | |
Object.keys(recordsHash).forEach((key) => { | |
recordsHash[key].forEach((record) => { | |
let listForKey = response[key] = Em.makeArray(response[key]); | |
const existingRecord = listForKey.findBy('id', record.id); | |
if(existingRecord) { | |
Em.merge(existingRecord, record); | |
} else { | |
listForKey.pushObject(record); | |
} | |
}); | |
}); | |
}); | |
return response; | |
} | |
serializeRecords(type, records, request, response, key) { | |
const _collection = Em.makeArray(records).map((record) => this.serializeRecord(type, record, request, key)); | |
return this.addCollectionToResponse(response || {}, _collection); | |
} | |
serializeRecord(type, record, request, key) { | |
const _model = this.mockSerializers[type]; | |
const _response = {}; | |
const _serializedRecord = _model.serialize(record, request); | |
_response[pluralize(key || _model.type)] = [_serializedRecord]; | |
_model.relationshipsFor(record, request).forEach((relationship) => { | |
this.serializeRelationship(relationship, type, record, request, _response); | |
}); | |
return _response; | |
} | |
serializeRelationship(relationship, type, record, request, response) { | |
let _fk, _fkid; | |
if(relationship.assoc === 'belongsTo') { | |
_fk = 'id'; | |
_fkid = record[relationship.fk]; | |
} else { | |
const inverseRel = this.getRelationship(relationship.type, relationship.inverseOf); | |
_fk = `${inverseRel.key}_id`; | |
_fkid = record.id; | |
} | |
const _collection = this.collectionFor(relationship.type); | |
if(!_fkid) { return; } | |
const _assocRecords = _collection.filterBy(_fk, _fkid); | |
if(!_assocRecords.length) { return; } | |
this.serializeRecords(relationship.type, _assocRecords, request, response, relationship.key); | |
} | |
getRelationship(recordType, relationshipKey) { | |
return this.mockSerializers[recordType].relsByKey([relationshipKey])[0]; | |
} | |
collectionFor(type) { | |
return this.db[pluralize(type)]; | |
} | |
} | |
export default SerializerMachine; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment