Skip to content

Commit d2e4062

Browse files
committed
make it harder to shoot yourself in the foot with unrelate. closes #470
1 parent 3cee53d commit d2e4062

File tree

4 files changed

+94
-27
lines changed

4 files changed

+94
-27
lines changed

‎doc/includes/API.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,9 @@ Doesn't delete the models. Only removes the connection. For ManyToMany relations
10561056
deletes the join column from the join table. For other relation types this sets the
10571057
join columns to null.
10581058

1059+
Note that, unlike for `relate`, you shouldn't pass arguments for the `unrelate` method.
1060+
Use `unrelate` like `delete` and filter the rows using the returned query builder.
1061+
10591062
##### Return value
10601063

10611064
Type|Description

‎lib/queryBuilder/QueryBuilder.js‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -810,29 +810,35 @@ class QueryBuilder extends QueryBuilderBase {
810810

811811
delete() {
812812
return writeOperation(this, () => {
813-
const deleteOperation = this._deleteOperationFactory(this);
813+
if (arguments.length) {
814+
throw new Error(`Don't pass arguments to delete(). You should use it like this: delete().where('foo', 'bar').andWhere(...)`);
815+
}
814816

815-
this.addOperation(deleteOperation, []);
817+
const deleteOperation = this._deleteOperationFactory(this);
818+
this.addOperation(deleteOperation, arguments);
816819
});
817820
}
818821

819822
del() {
820-
return this.delete();
823+
return this.delete.apply(this, arguments);
821824
}
822825

823-
relate(ids) {
826+
relate() {
824827
return writeOperation(this, () => {
825828
const relateOperation = this._relateOperationFactory(this);
826829

827-
this.addOperation(relateOperation, [ids]);
830+
this.addOperation(relateOperation, arguments);
828831
});
829832
}
830833

831834
unrelate() {
832835
return writeOperation(this, () => {
833-
const unrelateOperation = this._unrelateOperationFactory(this);
836+
if (arguments.length) {
837+
throw new Error(`Don't pass arguments to unrelate(). You should use it like this: unrelate().where('foo', 'bar').andWhere(...)`);
838+
}
834839

835-
this.addOperation(unrelateOperation, []);
840+
const unrelateOperation = this._unrelateOperationFactory(this);
841+
this.addOperation(unrelateOperation, arguments);
836842
});
837843
}
838844

‎tests/integration/eager.js‎

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,23 +1218,26 @@ module.exports = (session) => {
12181218
describe('QueryBuilder.modifyEager', () => {
12191219

12201220
it('should filter the eager query using relation expressions as paths', () => {
1221-
return Model1
1222-
.query()
1223-
.where('id', 1)
1224-
.modifyEager('model1Relation2.model2Relation1', builder => {
1225-
builder.where('Model1.id', 6);
1226-
})
1227-
.eager('model1Relation2.model2Relation1.[model1Relation1, model1Relation2]')
1228-
.filterEager('model1Relation2', builder => {
1229-
builder.where('model_2_prop_1', 'hejsan 2');
1230-
})
1231-
.then(models => {
1232-
expect(models[0].model1Relation2).to.have.length(1);
1233-
expect(models[0].model1Relation2[0].model2Prop1).to.equal('hejsan 2');
1221+
return Promise.all([Model1.WhereInEagerAlgorithm, Model1.JoinEagerAlgorithm].map(eagerAlgo => {
1222+
return Model1
1223+
.query()
1224+
.eagerAlgorithm(eagerAlgo)
1225+
.where('Model1.id', 1)
1226+
.modifyEager('model1Relation2.model2Relation1', builder => {
1227+
builder.where('Model1.id', 6);
1228+
})
1229+
.eager('model1Relation2.model2Relation1.[model1Relation1, model1Relation2]')
1230+
.filterEager('model1Relation2', builder => {
1231+
builder.where('model_2_prop_1', 'hejsan 2');
1232+
})
1233+
.then(models => {
1234+
expect(models[0].model1Relation2).to.have.length(1);
1235+
expect(models[0].model1Relation2[0].model2Prop1).to.equal('hejsan 2');
12341236

1235-
expect(models[0].model1Relation2[0].model2Relation1).to.have.length(1);
1236-
expect(models[0].model1Relation2[0].model2Relation1[0].id).to.equal(6);
1237-
});
1237+
expect(models[0].model1Relation2[0].model2Relation1).to.have.length(1);
1238+
expect(models[0].model1Relation2[0].model2Relation1[0].id).to.equal(6);
1239+
});
1240+
}));
12381241
});
12391242

12401243
it('should implicitly add selects for join columns if they are omitted in filterEager/modifyEager', () => {

‎tests/integration/unrelate.js‎

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ module.exports = (session) => {
5151
it('should unrelate', () => {
5252
return Model1
5353
.query()
54-
.where('id', 1)
55-
.first()
54+
.findById(1)
5655
.then(model => {
5756
return model
5857
.$relatedQuery('model1Relation1')
@@ -71,6 +70,25 @@ module.exports = (session) => {
7170
});
7271
});
7372

73+
it('should fail if arguments are given', (done) => {
74+
Model1
75+
.query()
76+
.findById(1)
77+
.then(model => {
78+
return model
79+
.$relatedQuery('model1Relation1')
80+
.unrelate(1);
81+
})
82+
.then(numUpdated => {
83+
done(new Error('should not get here'));
84+
})
85+
.catch(err => {
86+
expect(err.message).to.equal(`Don't pass arguments to unrelate(). You should use it like this: unrelate().where('foo', 'bar').andWhere(...)`);
87+
done();
88+
})
89+
.catch(done);
90+
});
91+
7492
});
7593

7694
describe('has many relation', () => {
@@ -151,6 +169,25 @@ module.exports = (session) => {
151169
});
152170
});
153171

172+
it('should fail if arguments are given', (done) => {
173+
Model1
174+
.query()
175+
.findById(1)
176+
.then(model => {
177+
return model
178+
.$relatedQuery('model1Relation2')
179+
.unrelate([1, 2])
180+
})
181+
.then(numUpdated => {
182+
done(new Error('should not get here'));
183+
})
184+
.catch(err => {
185+
expect(err.message).to.equal(`Don't pass arguments to unrelate(). You should use it like this: unrelate().where('foo', 'bar').andWhere(...)`);
186+
done();
187+
})
188+
.catch(done);
189+
});
190+
154191
});
155192

156193
describe('many to many relation', () => {
@@ -218,8 +255,7 @@ module.exports = (session) => {
218255
it('should unrelate multiple', () => {
219256
return Model2
220257
.query()
221-
.where('id_col', 1)
222-
.first()
258+
.findById(1)
223259
.then(model => {
224260
return model
225261
.$relatedQuery('model2Relation1')
@@ -239,6 +275,25 @@ module.exports = (session) => {
239275
});
240276
});
241277

278+
it('should fail if arguments are given', (done) => {
279+
Model2
280+
.query()
281+
.findById(1)
282+
.then(model => {
283+
return model
284+
.$relatedQuery('model2Relation1')
285+
.unrelate([1, 2])
286+
})
287+
.then(numUpdated => {
288+
done(new Error('should not get here'));
289+
})
290+
.catch(err => {
291+
expect(err.message).to.equal(`Don't pass arguments to unrelate(). You should use it like this: unrelate().where('foo', 'bar').andWhere(...)`);
292+
done();
293+
})
294+
.catch(done);
295+
});
296+
242297
});
243298

244299
describe('has one through relation', () => {

0 commit comments

Comments
 (0)