Skip to content
This repository has been archived by the owner on Aug 22, 2019. It is now read-only.

Commit

Permalink
Experimental fix for arrays of references. The issue in question is #1.
Browse files Browse the repository at this point in the history
WIP.
  • Loading branch information
jakubhomoly committed Mar 24, 2017
1 parent 5cf9f5f commit 05ec54c
Show file tree
Hide file tree
Showing 6 changed files with 384 additions and 228 deletions.
32 changes: 29 additions & 3 deletions dist/entities/instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ class Instance {
delete() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
this.storage.remove(this.getKey(), { cas: this.getCas() })
// TODO: add second arg { cas: this.getCas() } when CB is updated to 4.6.0
this.storage.remove(this.getKey())
.then(() => __awaiter(this, void 0, void 0, function* () {
let referencedKeysToDelete = new Set();
try {
Expand Down Expand Up @@ -161,8 +162,14 @@ class Instance {
*/
getDataForStorage() {
let storageData = Object.assign({}, this.modelInstance.data);
let monitoredKey = 0;
this.modelInstance.referencedModels.forEach(reference => {
lodash_1.set(storageData, reference.pathToModel, {
let baseKey = reference.pathToModel;
if (reference.pathToModel.includes('.')) {
baseKey = reference.pathToModel.replace('.', `[${monitoredKey}].`);
monitoredKey++;
}
lodash_1.set(storageData, baseKey, {
$type: 'reference',
docType: reference.model,
docId: reference.data.getId()
Expand All @@ -186,7 +193,26 @@ class Instance {
},
set(value) {
this.modelInstance.dirty = true;
this.modelInstance.data[name] = value;
// experimental fix for referenced arrays
if (Array.isArray(value)) {
let arrayEntries = {};
arrayEntries[name] = [];
value.forEach(entry => {
let referenceKey = Object.keys(entry)[0];
// only process entries that are arrays of references
/* istanbul ignore else */
if (referenceKey && entry[referenceKey] instanceof Instance) {
arrayEntries[name].push(entry);
}
});
/* istanbul ignore else */
if (Object.keys(arrayEntries).length > 0) {
this.findReferences(arrayEntries);
}
}
else {
this.modelInstance.data[name] = value;
}
}
});
this.modelInstance.monitoredProperties.add(name);
Expand Down
9 changes: 8 additions & 1 deletion dist/entities/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,18 @@ class Model {
this.storage.insert(instance.getKey(), instance.getDataForStorage())
.then(({ cas }) => __awaiter(this, void 0, void 0, function* () {
instance.setCas(cas);
let monitoredKey = 0;
for (let referenced of instance.getReferencedModels()) {
if (!referenced.data.getId()) {
continue;
}
lodash_1.set(instance, `${referenced.pathToModel}`, referenced.data);
let baseKey = referenced.pathToModel;
// in case the pathToModel is a deep reference
if (referenced.pathToModel.includes('.')) {
baseKey = referenced.pathToModel.replace('.', `[${monitoredKey}].`);
monitoredKey++;
}
lodash_1.set(instance, `${baseKey}`, referenced.data);
}
resolve(instance);
}))
Expand Down
37 changes: 34 additions & 3 deletions src/entities/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ export default class Instance {
*/
public async delete (): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.storage.remove(this.getKey(), { cas: this.getCas() })
// TODO: add second arg { cas: this.getCas() } when CB is updated to 4.6.0
this.storage.remove(this.getKey())
.then(async () => {
let referencedKeysToDelete = new Set()

Expand Down Expand Up @@ -201,8 +202,17 @@ export default class Instance {
public getDataForStorage (): {} {
let storageData = Object.assign({}, this.modelInstance.data)

let monitoredKey = 0

this.modelInstance.referencedModels.forEach(reference => {
set(storageData, reference.pathToModel, {
let baseKey = reference.pathToModel

if (reference.pathToModel.includes('.')) {
baseKey = reference.pathToModel.replace('.', `[${monitoredKey}].`)
monitoredKey++
}

set(storageData, baseKey, {
$type: 'reference',
docType: reference.model,
docId: reference.data.getId()
Expand All @@ -229,7 +239,28 @@ export default class Instance {
},
set (value) {
this.modelInstance.dirty = true
this.modelInstance.data[name] = value

// experimental fix for referenced arrays
if (Array.isArray(value)) {
let arrayEntries = {}
arrayEntries[name] = []

value.forEach(entry => {
let referenceKey = Object.keys(entry)[0]
// only process entries that are arrays of references
/* istanbul ignore else */
if (referenceKey && entry[referenceKey] instanceof Instance) {
arrayEntries[name].push(entry)
}
})

/* istanbul ignore else */
if (Object.keys(arrayEntries).length > 0) {
this.findReferences(arrayEntries)
}
} else {
this.modelInstance.data[name] = value
}
}
})

Expand Down
12 changes: 11 additions & 1 deletion src/entities/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,22 @@ export default class Model {
.then(async ({ cas }) => {
instance.setCas(cas)

let monitoredKey = 0

for (let referenced of instance.getReferencedModels()) {
if (!referenced.data.getId()) {
continue
}

set(instance, `${referenced.pathToModel}`, referenced.data)
let baseKey = referenced.pathToModel

// in case the pathToModel is a deep reference
if (referenced.pathToModel.includes('.')) {
baseKey = referenced.pathToModel.replace('.', `[${monitoredKey}].`)
monitoredKey++
}

set(instance, `${baseKey}`, referenced.data)
}

resolve(instance)
Expand Down
45 changes: 45 additions & 0 deletions test/features/general.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,48 @@ test.serial('workflow with referenced models', async () => {

await bmw.delete()
})

test.serial('it can save referenced arrays when editing an entry', async () => {
const WheelSchema = new Schema('Wheel', {
brand: Type.string()
})

const Wheel = settee.buildModel(WheelSchema)

const CarSchema = new Schema('Car', {
brand: Type.string(),
topSpeed: Type.number(),
taxPaid: Type.boolean(),
wheels: Type.array(Type.object({
wheelType: Type.reference(Wheel)
}))
})

const Car = settee.buildModel(CarSchema)

settee.registerModels([Car, Wheel])

let michelinWheel = await Wheel.create({
brand: 'Michelin'
})

let bridgestoneWheel = await Wheel.create({
brand: 'Bridgestone'
})

let bmw = await Car.create({
brand: 'BMW'
})

bmw.wheels = [
{ wheelType: michelinWheel },
{ wheelType: bridgestoneWheel }
]

await bmw.save()

bmw.brand.should.eq('BMW')
bmw.wheels.should.have.lengthOf(2)

await bmw.delete()
})
Loading

0 comments on commit 05ec54c

Please sign in to comment.