Merge branch 'master' into fix/refactor-modelto

This commit is contained in:
Fabien Franzen 2014-08-10 17:21:35 +02:00
commit 5a18839053
7 changed files with 51 additions and 18 deletions

View File

@ -1235,8 +1235,12 @@ var defineScope = require('./scope.js').defineScope;
* @param {ModelClass} [targetClass] The model class for the query, default to * @param {ModelClass} [targetClass] The model class for the query, default to
* the declaring model * the declaring model
*/ */
DataAccessObject.scope = function (name, query, targetClass) { DataAccessObject.scope = function (name, query, targetClass, methods, options) {
defineScope(this, targetClass || this, name, query); var cls = this;
if (options && options.isStatic === false) {
cls = cls.prototype;
}
defineScope(cls, targetClass || cls, name, query, methods, options);
}; };
/* /*

View File

@ -378,7 +378,7 @@ function isModelDataSourceAttached(model) {
DataSource.prototype.defineScopes = function (modelClass, scopes) { DataSource.prototype.defineScopes = function (modelClass, scopes) {
if(scopes) { if(scopes) {
for(var s in scopes) { for(var s in scopes) {
defineScope(modelClass, modelClass, s, scopes[s]); defineScope(modelClass, modelClass, s, scopes[s], {}, scopes[s].options);
} }
} }
}; };

View File

@ -564,7 +564,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
} }
return filter; return filter;
}, scopeMethods); }, scopeMethods, definition.options);
}; };
@ -1579,7 +1579,7 @@ RelationDefinition.embedsMany = function embedsMany(modelFrom, modelTo, params)
// 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); }, scopeMethods, definition.options);
scopeDefinition.related = scopeMethods.related; scopeDefinition.related = scopeMethods.related;
}; };
@ -1985,7 +1985,7 @@ RelationDefinition.referencesMany = function referencesMany(modelFrom, modelTo,
// 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); }, scopeMethods, definition.options);
scopeDefinition.related = scopeMethods.related; // bound to definition scopeDefinition.related = scopeMethods.related; // bound to definition
}; };

View File

@ -8,11 +8,13 @@ exports.defineScope = defineScope;
exports.mergeQuery = mergeQuery; exports.mergeQuery = mergeQuery;
function ScopeDefinition(definition) { function ScopeDefinition(definition) {
this.sourceModel = definition.sourceModel; this.isStatic = definition.isStatic;
this.targetModel = definition.targetModel || definition.sourceModel; this.modelFrom = definition.modelFrom;
this.modelTo = definition.modelTo || definition.modelFrom;
this.name = definition.name; this.name = definition.name;
this.params = definition.params; this.params = definition.params;
this.methods = definition.methods; this.methods = definition.methods;
this.options = definition.options;
} }
ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefresh, cb) { ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefresh, cb) {
@ -40,7 +42,7 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
|| actualRefresh) { || actualRefresh) {
// It either doesn't hit the cache or refresh is required // It either doesn't hit the cache or refresh is required
var params = mergeQuery(actualCond, scopeParams); var params = mergeQuery(actualCond, scopeParams);
return this.targetModel.find(params, function (err, data) { return this.modelTo.find(params, function (err, data) {
if (!err && saveOnCache) { if (!err && saveOnCache) {
defineCachedRelations(self); defineCachedRelations(self);
self.__cachedRelations[name] = data; self.__cachedRelations[name] = data;
@ -62,7 +64,7 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
* to return the query object * to return the query object
* @param methods An object of methods keyed by the method name to be bound to the class * @param methods An object of methods keyed by the method name to be bound to the class
*/ */
function defineScope(cls, targetClass, name, params, methods) { function defineScope(cls, targetClass, name, params, methods, options) {
// collect meta info about scope // collect meta info about scope
if (!cls._scopeMeta) { if (!cls._scopeMeta) {
@ -79,14 +81,27 @@ function defineScope(cls, targetClass, name, params, methods) {
} }
} }
options = options || {};
// Check if the cls is the class itself or its prototype
var isStatic = (typeof cls === 'function') || options.isStatic || false;
var definition = new ScopeDefinition({ var definition = new ScopeDefinition({
sourceModel: cls, isStatic: isStatic,
targetModel: targetClass, modelFrom: cls,
modelTo: targetClass,
name: name, name: name,
params: params, params: params,
methods: methods methods: methods,
options: options || {}
}); });
if(isStatic) {
cls.scopes = cls.scopes || {};
cls.scopes[name] = definition;
} else {
cls.constructor.scopes = cls.constructor.scopes || {};
cls.constructor.scopes[name] = definition;
}
// Define a property for the scope // Define a property for the scope
Object.defineProperty(cls, name, { Object.defineProperty(cls, name, {
enumerable: false, enumerable: false,
@ -115,7 +130,7 @@ function defineScope(cls, targetClass, name, params, methods) {
f._scope = typeof definition.params === 'function' ? f._scope = typeof definition.params === 'function' ?
definition.params.call(self) : definition.params; definition.params.call(self) : definition.params;
f._targetClass = definition.targetModel.modelName; f._targetClass = definition.modelTo.modelName;
if (f._scope.collect) { if (f._scope.collect) {
f._targetClass = i8n.capitalize(f._scope.collect); f._targetClass = i8n.capitalize(f._scope.collect);
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "loopback-datasource-juggler", "name": "loopback-datasource-juggler",
"version": "2.2.2", "version": "2.3.1",
"description": "LoopBack DataSoure Juggler", "description": "LoopBack DataSoure Juggler",
"keywords": [ "keywords": [
"StrongLoop", "StrongLoop",

View File

@ -284,17 +284,17 @@ describe('relations', function () {
Address.create({name: 'z'}, function (err, address) { Address.create({name: 'z'}, function (err, address) {
patient.address(address); patient.address(address);
patient.save(function() { patient.save(function() {
verify(physician); verify(physician, address.id);
}); });
}); });
}); });
}); });
function verify(physician) { function verify(physician, addressId) {
physician.patients({include: 'address'}, function (err, ch) { physician.patients({include: 'address'}, function (err, ch) {
should.not.exist(err); should.not.exist(err);
should.exist(ch); should.exist(ch);
ch.should.have.lengthOf(1); ch.should.have.lengthOf(1);
ch[0].addressId.should.equal(1); ch[0].addressId.should.eql(addressId);
var address = ch[0].address(); var address = ch[0].address();
should.exist(address); should.exist(address);
address.should.be.an.instanceof(Address); address.should.be.an.instanceof(Address);

View File

@ -9,6 +9,14 @@ describe('scope', function () {
db = getSchema(); db = getSchema();
Railway = db.define('Railway', { Railway = db.define('Railway', {
URID: {type: String, index: true} URID: {type: String, index: true}
}, {
scopes: {
highSpeed: {
where: {
highSpeed: true
}
}
}
}); });
Station = db.define('Station', { Station = db.define('Station', {
USID: {type: String, index: true}, USID: {type: String, index: true},
@ -24,9 +32,15 @@ describe('scope', function () {
Station.destroyAll(done); Station.destroyAll(done);
}); });
}); });
it('should define scope using options.scopes', function () {
Railway.scopes.should.have.property('highSpeed');
Railway.highSpeed.should.be.function;
});
it('should define scope with query', function (done) { it('should define scope with query', function (done) {
Station.scope('active', {where: {isActive: true}}); Station.scope('active', {where: {isActive: true}});
Station.scopes.should.have.property('active');
Station.active.create(function (err, station) { Station.active.create(function (err, station) {
should.not.exist(err); should.not.exist(err);
should.exist(station); should.exist(station);