Merge branch 'release/2.0.0' into production

This commit is contained in:
Miroslav Bajtoš 2014-07-22 20:31:38 +02:00
commit aebdb44149
5 changed files with 53 additions and 64 deletions

View File

@ -399,7 +399,8 @@ DataSource.prototype.defineRelations = function (modelClass, relations) {
var params = { var params = {
foreignKey: relation.foreignKey, foreignKey: relation.foreignKey,
as: name, as: name,
model: model model: model,
options: relation.options
}; };
if (throughModel) { if (throughModel) {
params.through = throughModel; params.through = throughModel;
@ -418,7 +419,8 @@ DataSource.prototype.defineRelations = function (modelClass, relations) {
foreignKey: relation.foreignKey, foreignKey: relation.foreignKey,
as: name, as: name,
model: targetModel, model: targetModel,
through: model through: model,
options: relation.options
}; };
modelClass[relation.type].call(modelClass, name, params); modelClass[relation.type].call(modelClass, name, params);
} }
@ -444,7 +446,8 @@ DataSource.prototype.defineRelations = function (modelClass, relations) {
var params = { var params = {
foreignKey: r.foreignKey, foreignKey: r.foreignKey,
as: rn, as: rn,
model: targetModel model: targetModel,
options: r.options
}; };
if (throughModel) { if (throughModel) {
params.through = throughModel; params.through = throughModel;

View File

@ -101,6 +101,12 @@ Inclusion.include = function (objects, include, cb) {
return; return;
} }
// Just skip if inclusion is disabled
if (relation.options.disableInclude) {
cb();
return;
}
// Calling the relation method for each object // Calling the relation method for each object
async.each(objs, function (obj, callback) { async.each(objs, function (obj, callback) {
if(relation.type === 'belongsTo') { if(relation.type === 'belongsTo') {

View File

@ -70,6 +70,7 @@ function RelationDefinition(definition) {
this.keyThrough = definition.keyThrough; this.keyThrough = definition.keyThrough;
this.multiple = (this.type !== 'belongsTo' && this.type !== 'hasOne'); this.multiple = (this.type !== 'belongsTo' && this.type !== 'hasOne');
this.properties = definition.properties || {}; this.properties = definition.properties || {};
this.options = definition.options || {};
this.scope = definition.scope; this.scope = definition.scope;
} }
@ -363,7 +364,8 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
modelTo: modelTo, modelTo: modelTo,
multiple: true, multiple: true,
properties: params.properties, properties: params.properties,
scope: params.scope scope: params.scope,
options: params.options
}); });
if (params.through) { if (params.through) {
@ -387,36 +389,12 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
}; };
var findByIdFunc = scopeMethods.findById; var findByIdFunc = scopeMethods.findById;
findByIdFunc.shared = true;
findByIdFunc.http = {verb: 'get', path: '/' + relationName + '/:fk'};
findByIdFunc.accepts = {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}};
findByIdFunc.description = 'Find a related item by id for ' + relationName;
findByIdFunc.returns = {arg: 'result', type: 'object', root: true};
modelFrom.prototype['__findById__' + relationName] = findByIdFunc; modelFrom.prototype['__findById__' + relationName] = findByIdFunc;
var destroyByIdFunc = scopeMethods.destroy; var destroyByIdFunc = scopeMethods.destroy;
destroyByIdFunc.shared = true;
destroyByIdFunc.http = {verb: 'delete', path: '/' + relationName + '/:fk'};
destroyByIdFunc.accepts = {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}};
destroyByIdFunc.description = 'Delete a related item by id for ' + relationName;
destroyByIdFunc.returns = {};
modelFrom.prototype['__destroyById__' + relationName] = destroyByIdFunc; modelFrom.prototype['__destroyById__' + relationName] = destroyByIdFunc;
var updateByIdFunc = scopeMethods.updateById; var updateByIdFunc = scopeMethods.updateById;
updateByIdFunc.shared = true;
updateByIdFunc.http = {verb: 'put', path: '/' + relationName + '/:fk'};
updateByIdFunc.accepts = {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}};
updateByIdFunc.description = 'Update a related item by id for ' + relationName;
updateByIdFunc.returns = {arg: 'result', type: 'object', root: true};
modelFrom.prototype['__updateById__' + relationName] = updateByIdFunc; modelFrom.prototype['__updateById__' + relationName] = updateByIdFunc;
if(definition.modelThrough) { if(definition.modelThrough) {
@ -425,42 +403,10 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
scopeMethods.remove = scopeMethod(definition, 'remove'); scopeMethods.remove = scopeMethod(definition, 'remove');
var addFunc = scopeMethods.add; var addFunc = scopeMethods.add;
addFunc.shared = true;
addFunc.http = {verb: 'put', path: '/' + relationName + '/rel/:fk'};
addFunc.accepts = {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}};
addFunc.description = 'Add a related item by id for ' + relationName;
addFunc.returns = {arg: relationName, type: 'object', root: true};
modelFrom.prototype['__link__' + relationName] = addFunc; modelFrom.prototype['__link__' + relationName] = addFunc;
var removeFunc = scopeMethods.remove; var removeFunc = scopeMethods.remove;
removeFunc.shared = true;
removeFunc.http = {verb: 'delete', path: '/' + relationName + '/rel/:fk'};
removeFunc.accepts = {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}};
removeFunc.description = 'Remove the ' + relationName + ' relation to an item by id';
removeFunc.returns = {};
modelFrom.prototype['__unlink__' + relationName] = removeFunc; modelFrom.prototype['__unlink__' + relationName] = removeFunc;
// FIXME: [rfeng] How to map a function with callback(err, true|false) to HEAD?
// true --> 200 and false --> 404?
/*
var existsFunc = scopeMethods.exists;
existsFunc.shared = true;
existsFunc.http = {verb: 'head', path: '/' + relationName + '/rel/:fk'};
existsFunc.accepts = {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}};
existsFunc.description = 'Check the existence of ' + relationName + ' relation to an item by id';
existsFunc.returns = {};
modelFrom.prototype['__exists__' + relationName] = existsFunc;
*/
} else { } else {
scopeMethods.create = scopeMethod(definition, 'create'); scopeMethods.create = scopeMethod(definition, 'create');
scopeMethods.build = scopeMethod(definition, 'build'); scopeMethods.build = scopeMethod(definition, 'build');
@ -872,7 +818,8 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
modelFrom: modelFrom, modelFrom: modelFrom,
keyFrom: fk, keyFrom: fk,
keyTo: idName, keyTo: idName,
modelTo: modelTo modelTo: modelTo,
options: params.options
}); });
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelTo.modelName); modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelTo.modelName);
@ -1082,7 +1029,8 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) {
keyFrom: pk, keyFrom: pk,
keyTo: fk, keyTo: fk,
modelTo: modelTo, modelTo: modelTo,
properties: params.properties properties: params.properties,
options: params.options
}); });
modelFrom.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName); modelFrom.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName);

View File

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

View File

@ -1,7 +1,7 @@
// This test written in mocha+should.js // This test written in mocha+should.js
var should = require('./init.js'); var should = require('./init.js');
var db, User, Post, Passport, City, Street, Building, Assembly, Part; var db, User, AccessToken, Post, Passport, City, Street, Building, Assembly, Part;
describe('include', function () { describe('include', function () {
@ -141,6 +141,19 @@ describe('include', function () {
}); });
}); });
it('should not fetch User - AccessTokens', function (done) {
User.find({include: ['accesstokens']}, function (err, users) {
should.not.exist(err);
should.exist(users);
users.length.should.be.ok;
users.forEach(function (user) {
var userObj = user.toJSON();
userObj.should.not.have.property('accesstokens');
});
done();
});
});
it('should support hasAndBelongsToMany', function (done) { it('should support hasAndBelongsToMany', function (done) {
Assembly.destroyAll(function(err) { Assembly.destroyAll(function(err) {
@ -185,6 +198,9 @@ function setup(done) {
name: String, name: String,
age: Number age: Number
}); });
AccessToken = db.define('AccessToken', {
token: String
});
Passport = db.define('Passport', { Passport = db.define('Passport', {
number: String number: String
}); });
@ -195,6 +211,10 @@ function setup(done) {
Passport.belongsTo('owner', {model: User}); Passport.belongsTo('owner', {model: User});
User.hasMany('passports', {foreignKey: 'ownerId'}); User.hasMany('passports', {foreignKey: 'ownerId'});
User.hasMany('posts', {foreignKey: 'userId'}); User.hasMany('posts', {foreignKey: 'userId'});
User.hasMany('accesstokens', {
foreignKey: 'userId',
options: {disableInclude: true}
});
Post.belongsTo('author', {model: User, foreignKey: 'userId'}); Post.belongsTo('author', {model: User, foreignKey: 'userId'});
Assembly = db.define('Assembly', { Assembly = db.define('Assembly', {
@ -226,10 +246,22 @@ function setup(done) {
function (items) { function (items) {
createdUsers = items; createdUsers = items;
createPassports(); createPassports();
createAccessTokens();
} }
); );
} }
function createAccessTokens() {
clearAndCreate(
AccessToken,
[
{token: '1', userId: createdUsers[0].id},
{token: '2', userId: createdUsers[1].id}
],
function (items) {}
);
}
function createPassports() { function createPassports() {
clearAndCreate( clearAndCreate(
Passport, Passport,