不要怂,就是干,撸起袖子干!

Commit b992988b by Mick Hansen

feat(include): provide basic include.association support (as opposed to include.model/as pair)

1 parent ed091ccb
var Association = function() {
};
module.exports = Association;
\ No newline at end of file
...@@ -2,10 +2,14 @@ ...@@ -2,10 +2,14 @@
var Utils = require('./../utils') var Utils = require('./../utils')
, Helpers = require('./helpers') , Helpers = require('./helpers')
, Transaction = require('../transaction'); , Transaction = require('../transaction')
, Association = require('./base')
, util = require('util');
module.exports = (function() { module.exports = (function() {
var BelongsTo = function(source, target, options) { var BelongsTo = function(source, target, options) {
Association.call(this);
this.associationType = 'BelongsTo'; this.associationType = 'BelongsTo';
this.source = source; this.source = source;
this.target = target; this.target = target;
...@@ -64,6 +68,8 @@ module.exports = (function() { ...@@ -64,6 +68,8 @@ module.exports = (function() {
}; };
}; };
util.inherits(BelongsTo, Association);
// the id is in the source table // the id is in the source table
BelongsTo.prototype.injectAttributes = function() { BelongsTo.prototype.injectAttributes = function() {
var newAttributes = {}; var newAttributes = {};
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
var Utils = require('./utils') var Utils = require('./utils')
, Instance = require('./instance') , Instance = require('./instance')
, Attribute = require('./model/attribute') , Attribute = require('./model/attribute')
, Association = require('./associations/base')
, DataTypes = require('./data-types') , DataTypes = require('./data-types')
, Util = require('util') , Util = require('util')
, sql = require('sql') , sql = require('sql')
...@@ -653,6 +654,7 @@ module.exports = (function() { ...@@ -653,6 +654,7 @@ module.exports = (function() {
* @param {Array<Object|Model>} [options.include] A list of associations to eagerly load using a left join. Supported is either `{ include: [ Model1, Model2, ...]}` or `{ include: [{ model: Model1, as: 'Alias' }]}`. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in the as attribute when eager loading Y). * @param {Array<Object|Model>} [options.include] A list of associations to eagerly load using a left join. Supported is either `{ include: [ Model1, Model2, ...]}` or `{ include: [{ model: Model1, as: 'Alias' }]}`. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in the as attribute when eager loading Y).
* @param {Model} [options.include[].model] The model you want to eagerly load * @param {Model} [options.include[].model] The model you want to eagerly load
* @param {String} [options.include[].as] The alias of the relation, in case the model you want to eagerly load is aliassed. For `hasOne` / `belongsTo`, this should be the singular name, and for `hasMany`, it should be the plural * @param {String} [options.include[].as] The alias of the relation, in case the model you want to eagerly load is aliassed. For `hasOne` / `belongsTo`, this should be the singular name, and for `hasMany`, it should be the plural
* @param {Association} [options.include[].association] The association you want to eagerly load. (This can be used instead of providing a model/as pair)
* @param {Object} [options.include[].where] Where clauses to apply to the child models. Note that this converts the eager load to an inner join, unless you explicitly set `required: true` * @param {Object} [options.include[].where] Where clauses to apply to the child models. Note that this converts the eager load to an inner join, unless you explicitly set `required: true`
* @param {Array<String>} [options.include[].attributes] A list of attributes to select from the child model * @param {Array<String>} [options.include[].attributes] A list of attributes to select from the child model
* @param {Boolean} [options.include[].required] If true, converts to an inner join, which means that the parent model will only be loaded if it has any matching children. True if `include.where` is set, false otherwise. * @param {Boolean} [options.include[].required] If true, converts to an inner join, which means that the parent model will only be loaded if it has any matching children. True if `include.where` is set, false otherwise.
...@@ -1766,10 +1768,12 @@ module.exports = (function() { ...@@ -1766,10 +1768,12 @@ module.exports = (function() {
// convert all included elements to { Model: Model } form // convert all included elements to { Model: Model } form
var includes = options.include = options.include.map(function(include) { var includes = options.include = options.include.map(function(include) {
if (include instanceof Model) { if (include instanceof Association) {
include = { association: include };
} else if (include instanceof Model) {
include = { model: include }; include = { model: include };
} else if (typeof include !== 'object') { } else if (typeof include !== 'object') {
throw new Error('Include unexpected. Element has to be either an instance of Model or an object.'); throw new Error('Include unexpected. Element has to be either a Model, an Association or an object.');
} else if (include.hasOwnProperty('daoFactory')) { } else if (include.hasOwnProperty('daoFactory')) {
include.model = include.daoFactory; include.model = include.daoFactory;
} }
...@@ -1814,10 +1818,12 @@ module.exports = (function() { ...@@ -1814,10 +1818,12 @@ module.exports = (function() {
Model.$validateIncludedElements = validateIncludedElements; Model.$validateIncludedElements = validateIncludedElements;
var validateIncludedElement = function(include, tableNames) { var validateIncludedElement = function(include, tableNames) {
if (!include.hasOwnProperty('model')) { if (!include.hasOwnProperty('model') && !include.hasOwnProperty('association')) {
throw new Error('Include malformed. Expected attributes: model'); throw new Error('Include malformed. Expected attributes: model or association');
} }
if (include.association) include.model = include.association.source;
tableNames[include.model.getTableName()] = true; tableNames[include.model.getTableName()] = true;
if (include.hasOwnProperty('attributes')) { if (include.hasOwnProperty('attributes')) {
...@@ -1839,7 +1845,7 @@ module.exports = (function() { ...@@ -1839,7 +1845,7 @@ module.exports = (function() {
} }
// check if the current Model is actually associated with the passed Model - or it's a pseudo include // check if the current Model is actually associated with the passed Model - or it's a pseudo include
var association = this.getAssociation(include.model, include.as); var association = include.association || this.getAssociation(include.model, include.as);
if (association) { if (association) {
include.association = association; include.association = association;
include.as = association.as; include.as = association.as;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* jshint expr: true */ /* jshint expr: true */
var chai = require('chai') var chai = require('chai')
, Sequelize = require('../index') , Sequelize = require('../index')
, Promise = Sequelize.Promise
, expect = chai.expect , expect = chai.expect
, Support = require(__dirname + '/support') , Support = require(__dirname + '/support')
, DataTypes = require(__dirname + "/../lib/data-types") , DataTypes = require(__dirname + "/../lib/data-types")
...@@ -54,6 +55,31 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -54,6 +55,31 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
it('should support including a belongsTo association rather than a model/as pair', function () {
var Company = this.sequelize.define('Company', {})
, Person = this.sequelize.define('Person', {});
Person.relation = {
Employer: Person.belongsTo(Company, {as: 'employer'})
};
return this.sequelize.sync({force: true}).then(function () {
return Promise.join(
Person.create(),
Company.create()
).spread(function (person, company) {
return person.setEmployer(company);
});
}).then(function () {
return Person.find({
include: [Person.relation.Employer]
}).then(function (person) {
expect(person).to.be.ok;
expect(person.employer).to.be.ok;
});
});
});
it('should support a simple nested belongsTo -> belongsTo include', function (done) { it('should support a simple nested belongsTo -> belongsTo include', function (done) {
var Task = this.sequelize.define('Task', {}) var Task = this.sequelize.define('Task', {})
, User = this.sequelize.define('User', {}) , User = this.sequelize.define('User', {})
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!