Skip to content
This repository has been archived by the owner on Dec 20, 2023. It is now read-only.

Commit

Permalink
adding some tests for eager loading
Browse files Browse the repository at this point in the history
  • Loading branch information
Dustin Smith committed Jun 29, 2016
1 parent df60e74 commit 963de42
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 58 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Expand Up @@ -28,4 +28,6 @@ after_script:
language: node_js
node_js:
- "4"
- "5"
- "5.6"
- "5.12"
- "stable"
16 changes: 15 additions & 1 deletion lib/dataset/query.js
Expand Up @@ -338,7 +338,13 @@ define({
return this.mergeOptions({distinct: args});
},

/*
/**
* Allows the loading of another query and combining them in one patio command.
* Queries can be related or completely unrelated.
* All data comes back as JSON NOT Patio models.
*
* @example
*
* DB.from('company').filter({name: 'Amazon'})
* .eager({
* // company from parent query is passed in and usable in the eager query.
Expand Down Expand Up @@ -394,6 +400,14 @@ define({
ds.rowCb = function (topLevelResults) {

function toObject(thing) {
if (!thing) {
return comb.when(thing);
}
if (Array.isArray(thing)) {
return comb.when(thing.map(function(item) {
return toObject(item);
}));
}
if ('toObject' in thing) {
return comb.when(thing.toObject());
}
Expand Down
49 changes: 0 additions & 49 deletions lib/model.js
Expand Up @@ -346,51 +346,6 @@ var Model = define([QueryPlugin, Middleware], {
return this._toObject(false);
},

/**
* Convert this model to an object including any associations passed in.
*
* This will not handle recursive associations and is not useful when working with
* eager loaded models.
*
* @return {Object} the object version of this model.
**/
toObjectWithAssociations: function(associations) {
if (!associations) {
return this.toObject();
}

var includes = [],
modelInstance = this,
json = this.toObject(),
associationJson = {};

if (Array.isArray(associations)) {
includes = includes.concat(associations);
} else {
includes.push(associations);
}

var whens = (includes || []).map(function(associationName) {
return modelInstance[associationName].chain(function(association) {
if (association) {
if (!Array.isArray(association)) { // one-to-one
associationJson[associationName] = association.toObject();
} else {
associationJson[associationName] = association.map(function(item) {
return item.toObject();
});
}
} else {
associationJson[associationName] = null;
}
});
});

return comb.when(whens).chain(function() {
return merge(json, associationJson);
});
},

/**
* Convert this model to JSON, containing column, value pairs.
*
Expand All @@ -400,10 +355,6 @@ var Model = define([QueryPlugin, Middleware], {
return this.toObject();
},

toJSONWithAssociations: function(associations) {
return this.toObjectWithAssociations(associations);
},

/**
* Convert this model to a string, containing column, value pairs.
*
Expand Down
7 changes: 5 additions & 2 deletions lib/plugins/association.js
Expand Up @@ -160,6 +160,8 @@ exports.AssociationPlugin = comb.define(null, {
/* Allows eager loading of an association. This does an extra SQL query for the association.
* It will load any association singular or plural.
*
* @example
*
* Person.eager('company').one()
* { id: 1,
* name: 'Obi-Wan',
Expand Down Expand Up @@ -187,10 +189,11 @@ exports.AssociationPlugin = comb.define(null, {
* id: 1,
* name: 'Jedi council'
* }
* },
* }]
*
*/
eager: function(associations) {
var model = new this({}, true),
var model = new this(),
includes = [],
associationsObj = {};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -62,6 +62,6 @@
"patio": "./bin/patio"
},
"engines": {
"node": ">=4.0.0"
"node": ">=4.0.0 <6.0.0"
}
}
179 changes: 179 additions & 0 deletions test/associations/staticEager.test.js
@@ -0,0 +1,179 @@
"use strict";

var it = require('it'),
assert = require('assert'),
helper = require("../data/oneToOne.helper.js"),
patio = require("../../lib"),
comb = require("comb");

var gender = ["M", "F"];

it.describe("patio.Model static eager method", function (it) {
var Works, Employee, DB;
it.beforeAll(function () {
Works = patio.addModel("works");
Works.manyToOne("employee", {fetchType: Works.fetchType.LAZY});
Employee = patio.addModel("employee");
Employee.oneToMany("works", {fetchType: Employee.fetchType.LAZY});
DB = null;
return helper.createSchemaAndSync(true).chain(function(db){
DB = db;
});
});


it.should("have associations", function () {
assert.deepEqual(Employee.associations, ["works"]);
assert.deepEqual(Works.associations, ["employee"]);
var emp = new Employee();
var work = new Works();
assert.deepEqual(emp.associations, ["works"]);
assert.deepEqual(work.associations, ["employee"]);
});

it.describe("load associations", function (it) {

it.beforeEach(function () {
return comb
.when([
Employee.remove(),
Works.remove()
])
.chain(function () {
return new Employee({
lastName: "last" + 1,
firstName: "first" + 1,
midInitial: "m",
gender: gender[1 % 2],
street: "Street " + 1,
city: "City " + 1,
works: [{
companyName: "Google",
salary: 100000
},{
companyName: "Alphabet",
salary: 100000
}]
}).save();
}).chain(function () {
return new Employee({
lastName: "Skywalker",
firstName: "Luke",
midInitial: "m",
gender: gender[1 % 2],
street: "Street " + 1,
city: "City " + 1,
works: {
companyName: "C2FO",
salary: 200000
}
}).save();
});

});

it.should("when querying", function () {
return comb
.when([Employee.eager('works').one(), Works.eager('employee').one()])
.chain(function (res) {
var emp = res[0], work = res[1];
var empWorks = emp.works, worksEmp = work.employee;
assert(emp.works[0].id, work.id);
assert(work.employee.id, emp.id);
});
});

it.should("when querying with filtering", function () {
return Employee.eager('works').filter({lastName: "Skywalker"}).one()
.chain(function (emp) {
assert(emp.id, emp.works[0].employeeId);
});
});

it.should("and load other eager queries", function () {
return Employee.eager('works').eager({
who: function(emp) {
return Employee.findById(emp.id);
}
}).one().chain(function (emp) {
assert(emp.id, emp.works[0].employeeId);
assert(emp.id, emp.who.id);
}).chain(function() {
// run same queries back to back
// make sure eager is not being cached across model instances
return Employee.eager('works').eager({
you: function(emp) {
return Employee.findById(emp.id);
}
}).one()
.chain(function (emp) {
assert(emp.id, emp.works[0].employeeId);
assert.isUndefined(emp.who);
assert(emp.id, emp.you.id);
});
});
});

});

it.describe("dataset loading", function (it) {

it.beforeEach(function () {
return comb
.when([
Employee.remove(),
Works.remove()
])
.chain(function () {
return new Employee({
lastName: "last" + 1,
firstName: "first" + 1,
midInitial: "m",
gender: gender[1 % 2],
street: "Street " + 1,
city: "City " + 1,
works: [{
companyName: "Google",
salary: 100000
},{
companyName: "Alphabet",
salary: 100000
}]
}).save();
}).chain(function () {
return new Employee({
lastName: "Skywalker",
firstName: "Luke",
midInitial: "m",
gender: gender[1 % 2],
street: "Street " + 1,
city: "City " + 1,
works: {
companyName: "C2FO",
salary: 200000
}
}).save();
});

});

it.should("and load other eager queries", function () {
return DB.from('employee').filter({lastName: 'Skywalker'})
.eager({
who: function(emp) {
return DB.from('works').filter({employeeId: emp.id}).one();
}
}).one()
.chain(function (emp) {
assert(emp.lastName, 'Skywalker');
assert(emp.who.companyName, 'C2FO');
assert(emp.id, emp.who.employeeId);
});
});

});

it.afterAll(function () {
return helper.dropModels();
});
});
8 changes: 4 additions & 4 deletions test/data/oneToOne.helper.js
Expand Up @@ -13,8 +13,8 @@ module.exports = {
};

function createSchemaAndSync(underscore) {
return createTables(underscore).chain(function(){
return patio.syncModels();
return createTables(underscore).chain(function(db){
return patio.syncModels().chain(db);
});
}

Expand Down Expand Up @@ -60,5 +60,5 @@ function createTables(underscore) {
this.salary("float", {size: [20, 8], allowNull: false});
this.foreignKey(underscore ? "employee_id" : "employeeId", "employee", {key: "id"});
});
});
}
}).chain(DB);
}
13 changes: 13 additions & 0 deletions test/dataset/query.test.js
Expand Up @@ -1786,6 +1786,19 @@ it.describe("Dataset queries", function (it) {
});
});

it.describe("#eager", function (it) {
var db = new MockDatabase();
var dataset = db.from("test").eager({
test: function() {
return db.from('test2').one();
}
}).select("name");

it.should("not effect main SQL query", function () {
assert.equal(dataset.sql, 'SELECT name FROM test');
});
});

it.describe("groupAndCount", function (it) {
var ds = new Dataset().from("test");

Expand Down

0 comments on commit 963de42

Please sign in to comment.