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

Commit de0801dd by Mick Hansen

merge

2 parents a0c2e7ff 947ee0b5
...@@ -30,3 +30,7 @@ branches: ...@@ -30,3 +30,7 @@ branches:
only: only:
- master - master
- milestones/2.0.0 - milestones/2.0.0
cache:
directories:
- node_modules
...@@ -16,6 +16,11 @@ To install 2.x.x branch - which has a unstable API and will break backwards comp ...@@ -16,6 +16,11 @@ To install 2.x.x branch - which has a unstable API and will break backwards comp
- [Getting Started](http://sequelizejs.com/articles/getting-started) - [Getting Started](http://sequelizejs.com/articles/getting-started)
- [Documentation](http://sequelizejs.com/docs) - [Documentation](http://sequelizejs.com/docs)
<<<<<<< HEAD
=======
- [Collaboration and pull requests](https://github.com/sequelize/sequelize/wiki/Collaboration)
- [Roadmap](https://github.com/sequelize/sequelize/wiki/Roadmap)
>>>>>>> master
## Important Notes ## ## Important Notes ##
...@@ -68,230 +73,3 @@ Also make sure to take a look at the examples in the repository. The website wil ...@@ -68,230 +73,3 @@ Also make sure to take a look at the examples in the repository. The website wil
Instructions for running samples are located in the [example directory](https://github.com/sequelize/sequelize/tree/master/examples). Try these samples in a live sandbox environment: Instructions for running samples are located in the [example directory](https://github.com/sequelize/sequelize/tree/master/examples). Try these samples in a live sandbox environment:
<a href="https://runnable.com/sequelize" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png"></a> <a href="https://runnable.com/sequelize" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png"></a>
## Roadmap
A very basic roadmap. Chances aren't too bad, that not mentioned things are implemented as well. Don't panic :)
### 1.7.0
- ~~Check if lodash is a proper alternative to current underscore usage.~~
- ~~Transactions~~
- Associations of not yet saved objects: [#864](https://github.com/sequelize/sequelize/issues/864)
- Support for update of tables without primary key
- ~~MariaDB support~~
- ~~Support for update and delete calls for whole tables without previous loading of instances~~ Implemented in [#569](https://github.com/sequelize/sequelize/pull/569) thanks to @optiltude
- Eager loading of nested associations [#388](https://github.com/sequelize/sequelize/issues/388)
- ~~Model#delete~~ (renamed to [Model.destroy()](http://sequelizejs.com/documentation#instances-destroy))
- ~~Validate a model before it gets saved.~~ Implemented in [#601](https://github.com/sequelize/sequelize/pull/601), thanks to @durango
- ~~Move validation of enum attribute value to validate method~~ Implemented in [#894](https://github.com/sequelize/sequelize/pull/894) thanks to @durango
- ~~BLOB~~ [#842](https://github.com/sequelize/sequelize/pull/842), thanks to @janmeier
- ~~Support for foreign keys~~ Implemented in [#595](https://github.com/sequelize/sequelize/pull/595), thanks to @optilude
- Support for socket paths. [#982](https://github.com/sequelize/sequelize/issues/982)
### 1.7.x
- Complete support for non-id primary keys
### 1.8.0
- API sugar (like Model.select().where().group().include().all())
- Schema dumping
- ~~enum support~~
- attributes / values of a dao instance should be scoped
### 2.0.0
- ~~save datetimes in UTC~~
- encapsulate attributes if a dao inside the attributes property
- ~~add getters and setters for dao~~ Implemented in [#538](https://github.com/sequelize/sequelize/pull/538), thanks to iamjochem
- add proper error message everywhere
- refactor validate() output data structure, separating field-specific errors
from general model validator errors (i.e.
`{fields: {field1: ['field1error1']}, model: ['modelError1']}` or similar)
## Collaboration 2.0 ##
I'm glad to get pull request if any functionality is missing or something is buggy. But _please_ ... run the tests before you send me the pull request.
Still interested? Coolio! Here is how to get started:
### 1. Prepare your environment ###
Here comes a little surprise: You need [Node.JS](http://nodejs.org). In order to be
a productive developer, I would recommend the latest v0.8. Also I usually recommend
[NVM](https://github.com/creationix/nvm).
Once Node.JS is installed on your computer, you will also have access to the lovely
Node Package Manager (NPM).
### 2. Install the dependencies ###
Just "cd" into sequelize directory and run `npm install`, see an example below:
```console
$ cd path/to/sequelize
$ npm install
```
### 3. Database... Come to me! ###
First class citizen of Sequelize was MySQL. Over time, Sequelize began to
become compatible to SQLite and PostgreSQL. In order to provide a fully
featured pull request, you would most likely want to install of them. Give
it a try, it's not that hard.
If you are too lazy or just don't know how to get this work,
feel free to join the IRC channel (freenode@#sequelizejs).
For MySQL and PostgreSQL you'll need to create a DB called `sequelize_test`.
For MySQL this would look like this:
```console
$ echo "CREATE DATABASE sequelize_test;" | mysql -uroot
```
**CLEVER NOTE:** your local MySQL install must be with username `root`
without password. If you want to customize that just hack in the
tests, but make sure to don't commit your credentials, we don't want
to expose your personal data in sequelize codebase ;)
**AND ONE LAST THING:** Once `npm install` worked for you (see below), you'll
get SQLite tests for free :)
#### 3a. Docker
If you don't feel like setting up databases and users, you can use our [docker](http://docker.io) [image](https://index.docker.io/u/mhansen/sequelize-contribution/) for sequelize contribution.
Getting the image:
```console
$ sudo docker pull mhansen/sequelize-contribution
```
Start the container and save references to container id and ip:
```console
$ CONTAINER=$(sudo docker run -d -i -t mhansen/sequelize-contribution)
$ CONTAINER_IP=$(sudo docker inspect -format='{{.NetworkSettings.IPAddress}}' $CONTAINER)
```
Run tests:
```console
$ SEQ_HOST=$CONTAINER_IP SEQ_USER=sequelize_test make all
```
Stop the container:
```console
$ sudo docker stop $CONTAINER
```
When running tests repeatedly, you only need to redo step 3 if you haven't stopped the container.
### 4. Run the tests ###
Right now, the test base is split into the `test` folder (which contains the
lovely [Mocha](http://visionmedia.github.io/mocha/) tests).
As you might haven't installed all of the supported SQL dialects, here is how
to run the test suites for your development environment:
```console
$ # run all tests at once:
$ make all
$ # run the buster specs for mysql:
$ make mysql
$ # run the buster specs for sqlite:
$ make sqlite
$ # run the buster specs for postgresql:
$ make pgsql
$ # alternatively you can pass database credentials with $variables when testing
$ DIALECT=dialect SEQ_DB=database SEQ_USER=user SEQ_PW=password make test
```
### 5. That's all ###
Just commit and send pull requests.
Happy hacking and thank you for contributing.
Ah and one last thing: If you think you deserve it, feel free to add yourself to the
`package.json`. Also I always look for projects which are using sequelize. If you have
one of them, drop me a line!
### 6. Some words about coding style ###
As people are regularly complaining about missing semi-colons and strangely formatted
things, I just want to explain the way I code JavaScript (including Sequelize
... obviously). I won't reject any pull-request because of having a different code
style than me but it would be good to have a consistent way of coding in the whole
project. Here are my rules of thumb:
- No semi-colons. Where possible I try to avoid semi-colons. Please don't discuss this topic with me. Thanks.
- Curly braces for single line if blocks. I always add curly braces to if blocks. Same for loops and other places.
- Spacing. Indentation = 2 spaces. Also I add a lot of spaces where possible. See below.
- Anonymous functions over names functions. Usually I declare a function and assign it to a variable: `var foo = function() {}`
- Variable declarations. If multiple variables are defined, I use a leading comma for separation.
- Camelcased variable names. No underscores.
- Make sure that key is in objects when iterating over it. See below.
#### 6.1. Spaces ####
Use spaces when defining functions.
```js
function(arg1, arg2, arg3) {
return 1
}
```
Use spaces for if statements.
```js
if (condition) {
// do something
} else {
// something else
}
```
#### 6.2. Variable declarations ####
```js
var num = 1
, user = new User()
, date = new Date()
```
#### 6.3. For-In-loops ####
```js
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(obj[key])
}
}
```
#### 6.4. JSHint options ####
```js
{
"globals": {
"spyOn": false,
"it": false,
"console": false,
"describe": false,
"expect": false,
"beforeEach": false,
"waits": false,
"waitsFor": false,
"runs": false
},
"camelcase": true,
"curly": true,
"forin": true,
"indent": 2,
"unused": true,
"asi": true,
"evil": false,
"laxcomma": true,
"es5": true
}
```
...@@ -86,7 +86,11 @@ module.exports = (function() { ...@@ -86,7 +86,11 @@ module.exports = (function() {
, primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id' , primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id'
this[self.identifier] = associatedObject ? associatedObject[primaryKey] : null this[self.identifier] = associatedObject ? associatedObject[primaryKey] : null
options = Utils._.extend({ fields: [ self.identifier ], allowNull: [self.identifier] }, options) options = Utils._.extend({
fields: [ self.identifier ],
allowNull: [self.identifier],
association: true
}, options)
// passes the changed field to save, so only that field get updated. // passes the changed field to save, so only that field get updated.
return this.save(options) return this.save(options)
......
...@@ -95,7 +95,8 @@ module.exports = (function() { ...@@ -95,7 +95,8 @@ module.exports = (function() {
.save( .save(
Utils._.extend({}, options, { Utils._.extend({}, options, {
fields: [self.identifier], fields: [self.identifier],
allowNull: [self.identifier] allowNull: [self.identifier],
association: true
}) })
) )
.success(function() { .success(function() {
......
...@@ -545,7 +545,7 @@ module.exports = (function() { ...@@ -545,7 +545,7 @@ module.exports = (function() {
return this.QueryInterface.rawSelect(this.getTableName(), options, 'count') return this.QueryInterface.rawSelect(this.getTableName(), options, 'count')
} }
DAOFactory.prototype.findAndCountAll = function(options) { DAOFactory.prototype.findAndCountAll = function(options, queryOptions) {
var self = this var self = this
// no limit, offset, order, attributes or include for the options given to count() // no limit, offset, order, attributes or include for the options given to count()
, copts = Utils._.omit(options || {}, ['offset', 'limit', 'order', 'include', 'attributes']) , copts = Utils._.omit(options || {}, ['offset', 'limit', 'order', 'include', 'attributes'])
...@@ -574,7 +574,7 @@ module.exports = (function() { ...@@ -574,7 +574,7 @@ module.exports = (function() {
return emit.okay(cnt) // no records, no need for another query return emit.okay(cnt) // no records, no need for another query
} }
self.findAll(options) self.findAll(options, queryOptions)
.on('sql', emit.sql) .on('sql', emit.sql)
.error(emit.err) .error(emit.err)
.success(function(rows) { .success(function(rows) {
...@@ -1313,6 +1313,9 @@ module.exports = (function() { ...@@ -1313,6 +1313,9 @@ module.exports = (function() {
include.attributes = Object.keys(include.daoFactory.attributes) include.attributes = Object.keys(include.daoFactory.attributes)
} }
// pseudo include just needed the attribute logic, return
if (include._pseudo) return include
if (include.hasOwnProperty('daoFactory') && (include.hasOwnProperty('as'))) { if (include.hasOwnProperty('daoFactory') && (include.hasOwnProperty('as'))) {
var usesAlias = (include.as !== include.daoFactory.tableName) var usesAlias = (include.as !== include.daoFactory.tableName)
, association = (usesAlias ? parent.getAssociationByAlias(include.as) : parent.getAssociation(include.daoFactory)) , association = (usesAlias ? parent.getAssociationByAlias(include.as) : parent.getAssociation(include.daoFactory))
...@@ -1322,10 +1325,35 @@ module.exports = (function() { ...@@ -1322,10 +1325,35 @@ module.exports = (function() {
include.as = Utils.singularize(include.daoFactory.tableName, include.daoFactory.options.language) include.as = Utils.singularize(include.daoFactory.tableName, include.daoFactory.options.language)
} }
// check if the current daoFactory is actually associated with the passed daoFactory // check if the current daoFactory is actually associated with the passed daoFactory - or it's a pseudo include
if (!!association && (!association.options.as || (association.options.as === include.as))) { if (association && (!association.options.as || (association.options.as === include.as))) {
include.association = association include.association = association
// If through, we create a pseudo child include, to ease our parsing later on
if (Object(include.association.through) === include.association.through) {
if (!include.include) include.include = []
var through = include.association.through
include.through = {
daoFactory: through,
as: Utils.singularize(through.tableName, through.options.language),
association: {
isSingleAssociation: true
},
_pseudo: true
}
include.include.push(include.through)
}
if (include.required === undefined) {
include.required = false
if (include.where) {
include.required = true
}
}
// Validate child includes
if (include.hasOwnProperty('include')) { if (include.hasOwnProperty('include')) {
validateIncludedElements(include) validateIncludedElements(include)
} }
......
...@@ -159,6 +159,7 @@ module.exports = (function() { ...@@ -159,6 +159,7 @@ module.exports = (function() {
this._customSetters[key].call(this, value, key) this._customSetters[key].call(this, value, key)
} else { } else {
// Check if we have included models, and if this key matches the include model names/aliases // Check if we have included models, and if this key matches the include model names/aliases
if (this.options && this.options.include && this.options.includeNames.indexOf(key) !== -1) { if (this.options && this.options.include && this.options.includeNames.indexOf(key) !== -1) {
// Pass it on to the include handler // Pass it on to the include handler
this._setInclude(key, value, options) this._setInclude(key, value, options)
...@@ -238,7 +239,7 @@ module.exports = (function() { ...@@ -238,7 +239,7 @@ module.exports = (function() {
includeValidated: true, includeValidated: true,
raw: options.raw raw: options.raw
}) })
, isEmpty = !Utils.firstValueOfHash(daoInstance.identifiers) , isEmpty = !Utils.firstValueOfHash(daoInstance.identifiers)
if (association.isSingleAssociation) { if (association.isSingleAssociation) {
accessor = Utils.singularize(accessor, self.sequelize.language) accessor = Utils.singularize(accessor, self.sequelize.language)
...@@ -270,6 +271,14 @@ module.exports = (function() { ...@@ -270,6 +271,14 @@ module.exports = (function() {
options.fields = this.attributes options.fields = this.attributes
} }
if (options.returning === undefined) {
if (options.association) {
options.returning = false
} else {
options.returning = true
}
}
var self = this var self = this
, values = {} , values = {}
, updatedAtAttr = Utils._.underscoredIf(this.__options.updatedAt, this.__options.underscored) , updatedAtAttr = Utils._.underscoredIf(this.__options.updatedAt, this.__options.underscored)
......
...@@ -173,13 +173,15 @@ module.exports = (function() { ...@@ -173,13 +173,15 @@ module.exports = (function() {
If you use a string, you have to escape it on your own. If you use a string, you have to escape it on your own.
*/ */
updateQuery: function(tableName, attrValueHash, where, options, attributes) { updateQuery: function(tableName, attrValueHash, where, options, attributes) {
options = options || {}
attrValueHash = Utils.removeNullValuesFromHash(attrValueHash, this.options.omitNull, options) attrValueHash = Utils.removeNullValuesFromHash(attrValueHash, this.options.omitNull, options)
var query var query
, values = [] , values = []
query = "UPDATE <%= table %> SET <%= values %> WHERE <%= where %>" query = "UPDATE <%= table %> SET <%= values %> WHERE <%= where %>"
if (this._dialect.supports['RETURNING']) { if (this._dialect.supports['RETURNING'] && (options.returning || options.returning === undefined)) {
query += " RETURNING *" query += " RETURNING *"
} }
...@@ -489,45 +491,80 @@ module.exports = (function() { ...@@ -489,45 +491,80 @@ module.exports = (function() {
, as = include.as , as = include.as
, joinQueryItem = "" , joinQueryItem = ""
, attributes , attributes
, association = include.association
, through = include.through
, joinType = include.required ? ' INNER JOIN ' : ' LEFT OUTER JOIN '
, where = {}
, whereOptions = Utils._.clone(options)
if (tableName !== parentTable) as = parentTable+'.'+include.as if (tableName !== parentTable) as = parentTable+'.'+include.as
if (include.where) {
for (var key in include.where) {
if (include.where.hasOwnProperty(key)) {
where[self.quoteIdentifier(as)+'.'+self.quoteIdentifiers(key)] = include.where[key]
}
}
include.where = where
whereOptions.keysEscaped = true
}
attributes = include.attributes.map(function(attr) { attributes = include.attributes.map(function(attr) {
return self.quoteIdentifier(as) + "." + self.quoteIdentifier(attr) + " AS " + self.quoteIdentifier(as + "." + attr) return self.quoteIdentifier(as) + "." + self.quoteIdentifier(attr) + " AS " + self.quoteIdentifier(as + "." + attr)
}) })
optAttributes = optAttributes.concat(attributes) optAttributes = optAttributes.concat(attributes)
if (Object(include.association.through) === include.association.through) { if (through) {
var primaryKeysSource = Object.keys(include.association.source.primaryKeys) var throughTable = through.daoFactory.tableName
, throughAs = as + "." + through.as
, throughAttributes = through.attributes.map(function(attr) {
return self.quoteIdentifier(throughAs) + "." + self.quoteIdentifier(attr) + " AS " + self.quoteIdentifier(throughAs + "." + attr)
})
optAttributes = optAttributes.concat(throughAttributes)
var primaryKeysSource = Object.keys(association.source.primaryKeys)
, tableSource = parentTable , tableSource = parentTable
, identSource = include.association.identifier , identSource = association.identifier
, attrSource = ((!include.association.source.hasPrimaryKeys || primaryKeysSource.length !== 1) ? 'id' : primaryKeysSource[0]) , attrSource = ((!association.source.hasPrimaryKeys || primaryKeysSource.length !== 1) ? 'id' : primaryKeysSource[0])
var primaryKeysTarget = Object.keys(include.association.target.primaryKeys) var primaryKeysTarget = Object.keys(association.target.primaryKeys)
, tableTarget = as , tableTarget = as
, identTarget = include.association.foreignIdentifier , identTarget = association.foreignIdentifier
, attrTarget = ((!include.association.target.hasPrimaryKeys || primaryKeysTarget.length !== 1) ? 'id' : primaryKeysTarget[0]) , attrTarget = ((!include.association.target.hasPrimaryKeys || primaryKeysTarget.length !== 1) ? 'id' : primaryKeysTarget[0])
var tableJunction = include.association.through.tableName joinQueryItem += joinType + self.quoteIdentifier(throughTable) + " AS " + self.quoteIdentifier(throughAs) + " ON "
joinQueryItem += " LEFT OUTER JOIN " + self.quoteIdentifier(tableJunction) + " ON "
joinQueryItem += self.quoteIdentifier(tableSource) + "." + self.quoteIdentifier(attrSource) + " = " joinQueryItem += self.quoteIdentifier(tableSource) + "." + self.quoteIdentifier(attrSource) + " = "
joinQueryItem += self.quoteIdentifier(tableJunction) + "." + self.quoteIdentifier(identSource) joinQueryItem += self.quoteIdentifier(throughAs) + "." + self.quoteIdentifier(identSource)
joinQueryItem += " LEFT OUTER JOIN " + self.quoteIdentifier(table) + " AS " + self.quoteIdentifier(as) + " ON " joinQueryItem += joinType + self.quoteIdentifier(table) + " AS " + self.quoteIdentifier(as) + " ON "
joinQueryItem += self.quoteIdentifier(tableTarget) + "." + self.quoteIdentifier(attrTarget) + " = " joinQueryItem += self.quoteIdentifier(tableTarget) + "." + self.quoteIdentifier(attrTarget) + " = "
joinQueryItem += self.quoteIdentifier(tableJunction) + "." + self.quoteIdentifier(identTarget) joinQueryItem += self.quoteIdentifier(throughAs) + "." + self.quoteIdentifier(identTarget)
if (include.where) {
joinQueryItem += " AND "+self.hashToWhereConditions(include.where, include.daoFactory, whereOptions)
}
} else { } else {
var primaryKeysLeft = ((include.association.associationType === 'BelongsTo') ? Object.keys(include.association.target.primaryKeys) : Object.keys(include.association.source.primaryKeys)) var primaryKeysLeft = ((association.associationType === 'BelongsTo') ? Object.keys(association.target.primaryKeys) : Object.keys(include.association.source.primaryKeys))
, tableLeft = ((include.association.associationType === 'BelongsTo') ? as : parentTable) , tableLeft = ((association.associationType === 'BelongsTo') ? as : parentTable)
, attrLeft = ((primaryKeysLeft.length !== 1) ? 'id' : primaryKeysLeft[0]) , attrLeft = ((primaryKeysLeft.length !== 1) ? 'id' : primaryKeysLeft[0])
, tableRight = ((include.association.associationType === 'BelongsTo') ? parentTable : as) , tableRight = ((association.associationType === 'BelongsTo') ? parentTable : as)
, attrRight = include.association.identifier , attrRight = association.identifier
joinQueryItem += " LEFT OUTER JOIN " + self.quoteIdentifier(table) + " AS " + self.quoteIdentifier(as) + " ON " + self.quoteIdentifier(tableLeft) + "." + self.quoteIdentifier(attrLeft) + " = " + self.quoteIdentifier(tableRight) + "." + self.quoteIdentifier(attrRight) joinQueryItem += joinType + self.quoteIdentifier(table) + " AS " + self.quoteIdentifier(as) + " ON "
joinQueryItem += self.quoteIdentifier(tableLeft) + "." + self.quoteIdentifier(attrLeft) + " = "
joinQueryItem += self.quoteIdentifier(tableRight) + "." + self.quoteIdentifier(attrRight)
if (include.where) {
joinQueryItem += " AND "+self.hashToWhereConditions(include.where, include.daoFactory, whereOptions)
}
} }
if (include.include) { if (include.include) {
include.include.forEach(function(childInclude) { include.include.forEach(function(childInclude) {
if (childInclude._pseudo) return
joinQueryItem += generateJoinQuery(childInclude, as) joinQueryItem += generateJoinQuery(childInclude, as)
}.bind(this)) }.bind(this))
} }
...@@ -808,15 +845,21 @@ module.exports = (function() { ...@@ -808,15 +845,21 @@ module.exports = (function() {
hashToWhereConditions: function(hash, dao, options) { hashToWhereConditions: function(hash, dao, options) {
var result = [] var result = []
options = options || {}
for (var key in hash) { for (var key in hash) {
var value = hash[key] var value = hash[key]
, _key , _key
, _value = null , _value = null
if(this.isAssociationFilter(key, dao, options)){ if (options.keysEscaped) {
_key = key = this.getAssociationFilterColumn(key, dao, options); _key = key
} else { } else {
_key = this.quoteIdentifiers(key) if(this.isAssociationFilter(key, dao, options)){
_key = key = this.getAssociationFilterColumn(key, dao, options);
} else {
_key = this.quoteIdentifiers(key)
}
} }
//handle qualified key names //handle qualified key names
......
...@@ -322,14 +322,19 @@ module.exports = (function() { ...@@ -322,14 +322,19 @@ module.exports = (function() {
, existingResult , existingResult
, calleeData , calleeData
, child , child
, calleeDataIgnore = ['__children']
if (options.includeNames) {
calleeDataIgnore = calleeDataIgnore.concat(options.includeNames)
}
data.forEach(function (row) { data.forEach(function (row) {
row = Dot.transform(row) row = Dot.transform(row)
calleeData = _.omit(row, options.includeNames) calleeData = _.omit(row, calleeDataIgnore)
existingResult = _.find(results, function (result) { existingResult = _.find(results, function (result) {
if (options.includeNames) { if (calleeDataIgnore) {
return Utils._.isEqual(_.omit(result, options.includeNames.concat(['__children'])), calleeData) return Utils._.isEqual(_.omit(result, calleeDataIgnore), calleeData)
} }
return Utils._.isEqual(result, calleeData) return Utils._.isEqual(result, calleeData)
}) })
...@@ -340,7 +345,9 @@ module.exports = (function() { ...@@ -340,7 +345,9 @@ module.exports = (function() {
for (var attrName in row) { for (var attrName in row) {
if (row.hasOwnProperty(attrName)) { if (row.hasOwnProperty(attrName)) {
// Child if object, and is an child include
child = Object(row[attrName]) === row[attrName] && options.includeMap && options.includeMap[attrName] child = Object(row[attrName]) === row[attrName] && options.includeMap && options.includeMap[attrName]
if (child) { if (child) {
if (!existingResult.__children) existingResult.__children = {} if (!existingResult.__children) existingResult.__children = {}
if (!existingResult.__children[attrName]) existingResult.__children[attrName] = [] if (!existingResult.__children[attrName]) existingResult.__children[attrName] = []
...@@ -350,10 +357,10 @@ module.exports = (function() { ...@@ -350,10 +357,10 @@ module.exports = (function() {
} }
} }
}) })
results.forEach(function (result) { results.forEach(function (result) {
_.each(result.__children, function (children, key) { _.each(result.__children, function (children, key) {
result[key] = groupJoinData(children, options.includeMap[key]) result[key] = groupJoinData(children, (options.includeMap && options.includeMap[key]))
}) })
delete result.__children delete result.__children
}) })
......
...@@ -133,6 +133,36 @@ describe(Support.getTestDialectTeaser("BelongsTo"), function() { ...@@ -133,6 +133,36 @@ describe(Support.getTestDialectTeaser("BelongsTo"), function() {
}) })
}) })
}) })
it('should not clobber atributes', function (done) {
var Comment = this.sequelize.define('comment', {
text: DataTypes.STRING
});
var Post = this.sequelize.define('post', {
title: DataTypes.STRING
});
Post.hasOne(Comment);
Comment.belongsTo(Post);
this.sequelize.sync().done(function (err) {
Post.create({
title: 'Post title',
}).done(function(err, post) {
Comment.create({
text: 'OLD VALUE',
}).done(function(err, comment) {
comment.setPost(post).done(function(err) {
expect(comment.text).to.equal('UPDATED VALUE');
done()
});
comment.text = 'UPDATED VALUE';
});
});
})
})
}) })
describe("Foreign key constraints", function() { describe("Foreign key constraints", function() {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!