Allow custom scopeMethods option (obj/fn) for relation scopes
This commit is contained in:
parent
06f2b32c21
commit
e888b8cff9
|
@ -52,7 +52,25 @@ function normalizeType(type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
function extendScopeMethods(definition, scopeMethods, ext) {
|
||||||
|
var relationClass = RelationClasses[definition.type];
|
||||||
|
if (definition.type === RelationTypes.hasMany && definition.modelThrough) {
|
||||||
|
relationClass = RelationClasses.hasManyThrough;
|
||||||
|
}
|
||||||
|
if (typeof ext === 'function') {
|
||||||
|
ext.call(definition, scopeMethods, relationClass);
|
||||||
|
} else if (typeof ext === 'object') {
|
||||||
|
for (var key in ext) {
|
||||||
|
scopeMethods[key] = function () {
|
||||||
|
var relation = new relationClass(definition, this);
|
||||||
|
return ext[key].apply(relation, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scopeMethods;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relation definition class. Use to define relationships between models.
|
* Relation definition class. Use to define relationships between models.
|
||||||
|
@ -518,7 +536,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter;
|
return filter;
|
||||||
}, scopeMethods);
|
}, extendScopeMethods(definition, scopeMethods, params.scopeMethods));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1536,12 +1554,14 @@ RelationDefinition.embedsMany = function embedsMany(modelFrom, modelTo, params)
|
||||||
scopeMethods.create = scopeMethod(definition, 'create');
|
scopeMethods.create = scopeMethod(definition, 'create');
|
||||||
scopeMethods.build = scopeMethod(definition, 'build');
|
scopeMethods.build = scopeMethod(definition, 'build');
|
||||||
|
|
||||||
|
scopeMethods.related = scopeMethod(definition, 'related'); // bound to definition
|
||||||
|
|
||||||
// Mix the property and scoped methods into the prototype class
|
// Mix the property and scoped methods into the prototype class
|
||||||
var scopeDefinition = defineScope(modelFrom.prototype, modelTo, accessorName, function () {
|
var scopeDefinition = defineScope(modelFrom.prototype, modelTo, accessorName, function () {
|
||||||
return {};
|
return {};
|
||||||
}, scopeMethods);
|
}, extendScopeMethods(definition, scopeMethods, params.scopeMethods));
|
||||||
|
|
||||||
scopeDefinition.related = scopeMethod(definition, 'related'); // bound to definition
|
scopeDefinition.related = scopeMethods.related;
|
||||||
};
|
};
|
||||||
|
|
||||||
EmbedsMany.prototype.related = function(receiver, scopeParams, condOrRefresh, cb) {
|
EmbedsMany.prototype.related = function(receiver, scopeParams, condOrRefresh, cb) {
|
||||||
|
@ -1934,12 +1954,14 @@ RelationDefinition.referencesMany = function referencesMany(modelFrom, modelTo,
|
||||||
scopeMethods.create = scopeMethod(definition, 'create');
|
scopeMethods.create = scopeMethod(definition, 'create');
|
||||||
scopeMethods.build = scopeMethod(definition, 'build');
|
scopeMethods.build = scopeMethod(definition, 'build');
|
||||||
|
|
||||||
|
scopeMethods.related = scopeMethod(definition, 'related');
|
||||||
|
|
||||||
// Mix the property and scoped methods into the prototype class
|
// Mix the property and scoped methods into the prototype class
|
||||||
var scopeDefinition = defineScope(modelFrom.prototype, modelTo, relationName, function () {
|
var scopeDefinition = defineScope(modelFrom.prototype, modelTo, relationName, function () {
|
||||||
return {};
|
return {};
|
||||||
}, scopeMethods);
|
}, extendScopeMethods(definition, scopeMethods, params.scopeMethods));
|
||||||
|
|
||||||
scopeDefinition.related = scopeMethod(definition, 'related'); // bound to definition
|
scopeDefinition.related = scopeMethods.related; // bound to definition
|
||||||
};
|
};
|
||||||
|
|
||||||
ReferencesMany.prototype.related = function(receiver, scopeParams, condOrRefresh, cb) {
|
ReferencesMany.prototype.related = function(receiver, scopeParams, condOrRefresh, cb) {
|
||||||
|
|
|
@ -1858,7 +1858,16 @@ describe('relations', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can be declared', function (done) {
|
it('can be declared', function (done) {
|
||||||
Category.referencesMany(Product);
|
Category.referencesMany(Product, { scopeMethods: {
|
||||||
|
reverse: function(cb) {
|
||||||
|
var modelInstance = this.modelInstance;
|
||||||
|
var fk = this.definition.keyFrom;
|
||||||
|
var ids = modelInstance[fk] || [];
|
||||||
|
modelInstance.updateAttribute(fk, ids.reverse(), function(err, inst) {
|
||||||
|
cb(err, inst[fk] || []);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} });
|
||||||
db.automigrate(done);
|
db.automigrate(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1887,7 +1896,7 @@ describe('relations', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create duplicate record on scope', function (done) {
|
it('should not allow duplicate record on scope', function (done) {
|
||||||
Category.findOne(function(err, cat) {
|
Category.findOne(function(err, cat) {
|
||||||
cat.productIds = [product2.id, product2.id];
|
cat.productIds = [product2.id, product2.id];
|
||||||
cat.save(function(err, p) {
|
cat.save(function(err, p) {
|
||||||
|
@ -2035,14 +2044,25 @@ describe('relations', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should allow custom scope methods - reverse', function(done) {
|
||||||
|
Category.findOne(function(err, cat) {
|
||||||
|
cat.products.reverse(function(err, ids) {
|
||||||
|
var expected = [product3.id, product2.id];
|
||||||
|
ids.should.eql(expected);
|
||||||
|
cat.productIds.should.eql(expected);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
it('should include related items from scope', function(done) {
|
it('should include related items from scope', function(done) {
|
||||||
Category.find({ include: 'products' }, function(err, categories) {
|
Category.find({ include: 'products' }, function(err, categories) {
|
||||||
categories.should.have.length(1);
|
categories.should.have.length(1);
|
||||||
var cat = categories[0].toObject();
|
var cat = categories[0].toObject();
|
||||||
cat.name.should.equal('Category A');
|
cat.name.should.equal('Category A');
|
||||||
cat.products.should.have.length(2);
|
cat.products.should.have.length(2);
|
||||||
cat.products[0].id.should.eql(product2.id);
|
cat.products[0].id.should.eql(product3.id);
|
||||||
cat.products[1].id.should.eql(product3.id);
|
cat.products[1].id.should.eql(product2.id);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue