dao.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. var Utils = require("./utils")
  2. , Mixin = require("./associations/mixin")
  3. , DaoValidator = require("./dao-validator")
  4. , DataTypes = require("./data-types")
  5. , hstore = require('./dialects/postgres/hstore')
  6. , _ = require('lodash')
  7. module.exports = (function() {
  8. var DAO = function(values, options) {
  9. this.dataValues = {}
  10. this._previousDataValues = {}
  11. this.__options = this.__factory.options
  12. this.options = options
  13. this.hasPrimaryKeys = this.__factory.options.hasPrimaryKeys
  14. // What is selected values even used for?
  15. this.selectedValues = options.include ? _.omit(values, options.includeNames) : values
  16. this.__eagerlyLoadedAssociations = []
  17. this.isNewRecord = options.isNewRecord
  18. initValues.call(this, values, options);
  19. }
  20. Utils._.extend(DAO.prototype, Mixin.prototype)
  21. Object.defineProperty(DAO.prototype, 'sequelize', {
  22. get: function(){ return this.__factory.daoFactoryManager.sequelize }
  23. })
  24. Object.defineProperty(DAO.prototype, 'QueryInterface', {
  25. get: function(){ return this.sequelize.getQueryInterface() }
  26. })
  27. Object.defineProperty(DAO.prototype, 'isDeleted', {
  28. get: function() {
  29. return this.Model._timestampAttributes.deletedAt && this.dataValues[this.Model._timestampAttributes.deletedAt] !== null
  30. }
  31. })
  32. Object.defineProperty(DAO.prototype, 'values', {
  33. get: function() {
  34. return this.get()
  35. }
  36. })
  37. Object.defineProperty(DAO.prototype, 'isDirty', {
  38. get: function() {
  39. return !!this.changed()
  40. }
  41. })
  42. Object.defineProperty(DAO.prototype, 'primaryKeyValues', {
  43. get: function() {
  44. var result = {}
  45. , self = this
  46. Utils._.each(this.__factory.primaryKeys, function(_, attr) {
  47. result[attr] = self.dataValues[attr]
  48. })
  49. return result
  50. }
  51. })
  52. Object.defineProperty(DAO.prototype, "identifiers", {
  53. get: function() {
  54. var primaryKeys = Object.keys(this.__factory.primaryKeys)
  55. , result = {}
  56. , self = this
  57. if (!this.__factory.hasPrimaryKeys) {
  58. primaryKeys = ['id']
  59. }
  60. primaryKeys.forEach(function(identifier) {
  61. result[identifier] = self.dataValues[identifier]
  62. })
  63. return result
  64. }
  65. })
  66. DAO.prototype.getDataValue = function(key) {
  67. return this.dataValues[key]
  68. }
  69. DAO.prototype.setDataValue = function(key, value) {
  70. this.dataValues[key] = value
  71. }
  72. DAO.prototype.get = function (key) {
  73. if (key) {
  74. if (this._customGetters[key]) {
  75. return this._customGetters[key].call(this, key)
  76. }
  77. return this.dataValues[key]
  78. }
  79. if (this._hasCustomGetters) {
  80. var values = {}
  81. , key
  82. for (key in this._customGetters) {
  83. if (this._customGetters.hasOwnProperty(key)) {
  84. values[key] = this.get(key)
  85. }
  86. }
  87. for (key in this.dataValues) {
  88. if (!values.hasOwnProperty(key) && this.dataValues.hasOwnProperty(key)) {
  89. values[key] = this.dataValues[key]
  90. }
  91. }
  92. return values
  93. }
  94. return this.dataValues
  95. }
  96. DAO.prototype.set = function (key, value, options) {
  97. var values
  98. , originalValue
  99. if (typeof key === "object") {
  100. values = key
  101. options = value
  102. options || (options = {})
  103. if (options.reset) {
  104. this.dataValues = {}
  105. }
  106. // If raw, and we're not dealing with includes, just set it straight on the dataValues object
  107. if (options.raw && !(this.options && this.options.include) && !this._hasBooleanAttributes) {
  108. if (Object.keys(this.dataValues).length) {
  109. this.dataValues = _.extend(this.dataValues, values)
  110. } else {
  111. this.dataValues = values
  112. }
  113. // If raw, .changed() shouldn't be true
  114. this._previousDataValues = _.clone(this.dataValues)
  115. } else {
  116. // Loop and call set
  117. for (key in values) {
  118. this.set(key, values[key], options)
  119. }
  120. if (options.raw) {
  121. // If raw, .changed() shouldn't be true
  122. this._previousDataValues = _.clone(this.dataValues)
  123. }
  124. }
  125. } else {
  126. options || (options = {})
  127. originalValue = this.dataValues[key]
  128. // If not raw, and there's a customer setter
  129. if (!options.raw && this._customSetters[key]) {
  130. this._customSetters[key].call(this, value, key)
  131. } else {
  132. // Check if we have included models, and if this key matches the include model names/aliases
  133. if (this.options && this.options.include && this.options.includeNames.indexOf(key) !== -1) {
  134. // Pass it on to the include handler
  135. this._setInclude(key, value, options)
  136. return
  137. } else {
  138. // If not raw, and attribute is not in model definition, return
  139. if (!options.raw && !this._isAttribute(key)) {
  140. return;
  141. }
  142. // If attempting to set primary key and primary key is already defined, return
  143. if (this._hasPrimaryKeys && originalValue && this._isPrimaryKey(key)) {
  144. return
  145. }
  146. // If attempting to set generated id and id is already defined, return
  147. // This is hack since generated id is not in primaryKeys, although it should be
  148. if (originalValue && key === "id") {
  149. return
  150. }
  151. // If attempting to set read only attributes, return
  152. if (!options.raw && this._hasReadOnlyAttributes && this._isReadOnlyAttribute(key)) {
  153. return
  154. }
  155. // Convert boolean-ish values to booleans
  156. if (this._hasBooleanAttributes && this._isBooleanAttribute(key) && value !== null && value !== undefined) {
  157. value = !!value
  158. }
  159. // Convert date fields to real date objects
  160. if (this._hasDateAttributes && this._isDateAttribute(key) && value !== null && !(value instanceof Date)) {
  161. value = new Date(value)
  162. }
  163. if (originalValue !== value) {
  164. this._previousDataValues[key] = originalValue
  165. }
  166. this.dataValues[key] = value
  167. }
  168. }
  169. }
  170. }
  171. DAO.prototype.changed = function(key) {
  172. if (key) {
  173. if (this._isDateAttribute(key) && this._previousDataValues[key] && this.dataValues[key]) {
  174. return this._previousDataValues[key].valueOf() !== this.dataValues[key].valueOf()
  175. }
  176. return this._previousDataValues[key] !== this.dataValues[key]
  177. }
  178. var changed = Object.keys(this.dataValues).filter(function (key) {
  179. return this.changed(key)
  180. }.bind(this))
  181. return changed.length ? changed : false
  182. }
  183. DAO.prototype.previous = function(key) {
  184. return this._previousDataValues[key]
  185. }
  186. DAO.prototype._setInclude = function(key, value, options) {
  187. if (!Array.isArray(value)) value = [value]
  188. if (value[0] instanceof DAO) {
  189. value = value.map(function (instance) {
  190. return instance.dataValues
  191. })
  192. }
  193. var include = _.find(this.options.include, function (include) {
  194. return include.as === key || (include.as.slice(0,1).toLowerCase() + include.as.slice(1)) === key
  195. })
  196. var association = include.association
  197. , self = this
  198. var accessor = Utils._.camelize(key)
  199. // downcase the first char
  200. accessor = accessor.slice(0,1).toLowerCase() + accessor.slice(1)
  201. value.forEach(function(data) {
  202. var daoInstance = include.daoFactory.build(data, {
  203. isNewRecord: false,
  204. isDirty: false,
  205. include: include.include,
  206. includeNames: include.includeNames,
  207. includeMap: include.includeMap,
  208. includeValidated: true,
  209. raw: options.raw
  210. })
  211. , isEmpty = !Utils.firstValueOfHash(daoInstance.identifiers)
  212. if (association.isSingleAssociation) {
  213. accessor = Utils.singularize(accessor, self.sequelize.language)
  214. self.dataValues[accessor] = isEmpty ? null : daoInstance
  215. self[accessor] = self.dataValues[accessor]
  216. } else {
  217. if (!self.dataValues[accessor]) {
  218. self.dataValues[accessor] = []
  219. self[accessor] = self.dataValues[accessor]
  220. }
  221. if (!isEmpty) {
  222. self.dataValues[accessor].push(daoInstance)
  223. }
  224. }
  225. }.bind(this))
  226. };
  227. // if an array with field names is passed to save()
  228. // only those fields will be updated
  229. DAO.prototype.save = function(fieldsOrOptions, options) {
  230. if (fieldsOrOptions instanceof Array) {
  231. fieldsOrOptions = { fields: fieldsOrOptions }
  232. }
  233. options = Utils._.extend({}, options, fieldsOrOptions)
  234. if (!options.fields) {
  235. options.fields = Object.keys(this.Model.attributes)
  236. }
  237. if (options.returning === undefined) {
  238. if (options.association) {
  239. options.returning = false
  240. } else {
  241. options.returning = true
  242. }
  243. }
  244. var self = this
  245. , values = {}
  246. , updatedAtAttr = this.Model._timestampAttributes.updatedAt
  247. , createdAtAttr = this.Model._timestampAttributes.createdAt
  248. if (options.fields) {
  249. if (updatedAtAttr && options.fields.indexOf(updatedAtAttr) === -1) {
  250. options.fields.push(updatedAtAttr)
  251. }
  252. if (createdAtAttr && options.fields.indexOf(createdAtAttr) === -1 && this.isNewRecord === true) {
  253. options.fields.push(createdAtAttr)
  254. }
  255. }
  256. return new Utils.CustomEventEmitter(function(emitter) {
  257. self.hookValidate().error(function(err) {
  258. emitter.emit('error', err)
  259. }).success(function() {
  260. options.fields.forEach(function(field) {
  261. if (self.dataValues[field] !== undefined) {
  262. values[field] = self.dataValues[field]
  263. }
  264. })
  265. for (var attrName in self.daoFactory.rawAttributes) {
  266. if (self.daoFactory.rawAttributes.hasOwnProperty(attrName)) {
  267. var definition = self.daoFactory.rawAttributes[attrName]
  268. , isHstore = !!definition.type && !!definition.type.type && definition.type.type === DataTypes.HSTORE.type
  269. , isEnum = definition.type && (definition.type.toString() === DataTypes.ENUM.toString())
  270. , isMySQL = ['mysql', 'mariadb'].indexOf(self.daoFactory.daoFactoryManager.sequelize.options.dialect) !== -1
  271. , ciCollation = !!self.daoFactory.options.collate && self.daoFactory.options.collate.match(/_ci$/i)
  272. , valueOutOfScope
  273. // Unfortunately for MySQL CI collation we need to map/lowercase values again
  274. if (isEnum && isMySQL && ciCollation && (attrName in values) && values[attrName]) {
  275. var scopeIndex = (definition.values || []).map(function(d) { return d.toLowerCase() }).indexOf(values[attrName].toLowerCase())
  276. valueOutOfScope = scopeIndex === -1
  277. // We'll return what the actual case will be, since a simple SELECT query would do the same...
  278. if (!valueOutOfScope) {
  279. values[attrName] = definition.values[scopeIndex]
  280. }
  281. }
  282. if (isHstore) {
  283. if (typeof values[attrName] === "object") {
  284. values[attrName] = hstore.stringify(values[attrName])
  285. }
  286. }
  287. }
  288. }
  289. if (updatedAtAttr) {
  290. values[updatedAtAttr] = (
  291. (
  292. self.isNewRecord
  293. && !!self.daoFactory.rawAttributes[updatedAtAttr]
  294. && !!self.daoFactory.rawAttributes[updatedAtAttr].defaultValue
  295. )
  296. ? self.daoFactory.rawAttributes[updatedAtAttr].defaultValue
  297. : Utils.now(self.sequelize.options.dialect))
  298. }
  299. if (self.isNewRecord && createdAtAttr && !values[createdAtAttr]) {
  300. values[createdAtAttr] = (
  301. (
  302. !!self.daoFactory.rawAttributes[createdAtAttr]
  303. && !!self.daoFactory.rawAttributes[createdAtAttr].defaultValue
  304. )
  305. ? self.daoFactory.rawAttributes[createdAtAttr].defaultValue
  306. : values[updatedAtAttr])
  307. }
  308. var query = null
  309. , args = []
  310. , hook = ''
  311. if (self.isNewRecord) {
  312. query = 'insert'
  313. args = [self, self.QueryInterface.QueryGenerator.addSchema(self.__factory), values, options]
  314. hook = 'Create'
  315. } else {
  316. var identifier = self.__options.hasPrimaryKeys ? self.primaryKeyValues : { id: self.id }
  317. if (identifier === null && self.__options.whereCollection !== null) {
  318. identifier = self.__options.whereCollection;
  319. }
  320. query = 'update'
  321. args = [self, self.QueryInterface.QueryGenerator.addSchema(self.__factory), values, identifier, options]
  322. hook = 'Update'
  323. }
  324. // Add the values to the DAO
  325. self.dataValues = _.extend(self.dataValues, values)
  326. // Run the beforeCreate / beforeUpdate hook
  327. self.__factory.runHooks('before' + hook, self, function(err) {
  328. if (!!err) {
  329. return emitter.emit('error', err)
  330. }
  331. // dataValues might have changed inside the hook, rebuild
  332. // the values hash
  333. values = {}
  334. options.fields.forEach(function(field) {
  335. if (self.dataValues[field] !== undefined) {
  336. values[field] = self.dataValues[field]
  337. }
  338. })
  339. args[2] = values
  340. self.QueryInterface[query].apply(self.QueryInterface, args)
  341. .proxy(emitter, {events: ['sql']})
  342. .error(function(err) {
  343. if (!!self.__options.uniqueKeys && err.code && self.QueryInterface.QueryGenerator.uniqueConstraintMapping.code === err.code) {
  344. var fields = self.QueryInterface.QueryGenerator.uniqueConstraintMapping.map(err.toString())
  345. if (fields !== false) {
  346. fields = fields.filter(function(f) { return f !== self.daoFactory.tableName; })
  347. Utils._.each(self.__options.uniqueKeys, function(value, key) {
  348. if (Utils._.isEqual(value.fields, fields) && !!value.msg) {
  349. err = value.msg
  350. }
  351. })
  352. }
  353. }
  354. emitter.emit('error', err)
  355. })
  356. .success(function(result) {
  357. // Transfer database generated values (defaults, autoincrement, etc)
  358. values = _.extend(values, result.dataValues)
  359. // Ensure new values are on DAO, and reset previousDataValues
  360. result.dataValues = _.extend(result.dataValues, values)
  361. result._previousDataValues = _.clone(result.dataValues)
  362. self.__factory.runHooks('after' + hook, result, function(err) {
  363. if (!!err) {
  364. return emitter.emit('error', err)
  365. }
  366. emitter.emit('success', result)
  367. })
  368. })
  369. })
  370. })
  371. }).run()
  372. }
  373. /*
  374. * Refresh the current instance in-place, i.e. update the object with current data from the DB and return the same object.
  375. * This is different from doing a `find(DAO.id)`, because that would create and return a new object. With this method,
  376. * all references to the DAO are updated with the new data and no new objects are created.
  377. *
  378. * @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
  379. */
  380. DAO.prototype.reload = function(options) {
  381. var where = [
  382. this.QueryInterface.quoteIdentifier(this.Model.getTableName()) + '.' + this.QueryInterface.quoteIdentifier(this.Model.primaryKeyAttributes[0] || 'id') + '=?',
  383. this.get(this.Model.primaryKeyAttributes[0] || 'id', {raw: true})
  384. ]
  385. return new Utils.CustomEventEmitter(function(emitter) {
  386. this.__factory.find({
  387. where: where,
  388. limit: 1,
  389. include: this.options.include || null
  390. }, options)
  391. .on('sql', function(sql) { emitter.emit('sql', sql) })
  392. .on('error', function(error) { emitter.emit('error', error) })
  393. .on('success', function(obj) {
  394. this.set(obj.dataValues, {raw: true, reset: true})
  395. this.isDirty = false
  396. emitter.emit('success', this)
  397. }.bind(this))
  398. }.bind(this)).run()
  399. }
  400. /*
  401. * Validate this dao's attribute values according to validation rules set in the dao definition.
  402. *
  403. * @return null if and only if validation successful; otherwise an object containing { field name : [error msgs] } entries.
  404. */
  405. DAO.prototype.validate = function(object) {
  406. var validator = new DaoValidator(this, object)
  407. , errors = validator.validate()
  408. return (Utils._.isEmpty(errors) ? null : errors)
  409. }
  410. /*
  411. * Validate this dao's attribute values according to validation rules set in the dao definition.
  412. *
  413. * @return CustomEventEmitter with null if validation successful; otherwise an object containing { field name : [error msgs] } entries.
  414. */
  415. DAO.prototype.hookValidate = function(object) {
  416. var validator = new DaoValidator(this, object)
  417. return validator.hookValidate()
  418. }
  419. DAO.prototype.updateAttributes = function(updates, options) {
  420. if (options instanceof Array) {
  421. options = { fields: options }
  422. }
  423. this.set(updates)
  424. return this.save(options)
  425. }
  426. DAO.prototype.setAttributes = function(updates) {
  427. this.set(updates)
  428. }
  429. DAO.prototype.destroy = function(options) {
  430. options = options || {}
  431. options.force = options.force === undefined ? false : Boolean(options.force)
  432. var self = this
  433. , query = null
  434. return new Utils.CustomEventEmitter(function(emitter) {
  435. self.daoFactory.runHooks(self.daoFactory.options.hooks.beforeDestroy, self, function(err) {
  436. if (!!err) {
  437. return emitter.emit('error', err)
  438. }
  439. if (self.Model._timestampAttributes.deletedAt && options.force === false) {
  440. self.dataValues[self.Model._timestampAttributes.deletedAt] = new Date()
  441. query = self.save(options)
  442. } else {
  443. var identifier = self.__options.hasPrimaryKeys ? self.primaryKeyValues : { id: self.id };
  444. query = self.QueryInterface.delete(self, self.QueryInterface.QueryGenerator.addSchema(self.__factory.tableName, self.__factory.options.schema), identifier, options)
  445. }
  446. query.on('sql', function(sql) {
  447. emitter.emit('sql', sql)
  448. })
  449. .error(function(err) {
  450. emitter.emit('error', err)
  451. })
  452. .success(function(results) {
  453. self.daoFactory.runHooks(self.daoFactory.options.hooks.afterDestroy, self, function(err) {
  454. if (!!err) {
  455. return emitter.emit('error', err)
  456. }
  457. emitter.emit('success', results)
  458. })
  459. })
  460. })
  461. }).run()
  462. }
  463. DAO.prototype.increment = function(fields, countOrOptions) {
  464. Utils.validateParameter(countOrOptions, Object, {
  465. optional: true,
  466. deprecated: 'number',
  467. deprecationWarning: "Increment expects an object as second parameter. Please pass the incrementor as option! ~> instance.increment(" + JSON.stringify(fields) + ", { by: " + countOrOptions + " })"
  468. })
  469. var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : { id: this.id }
  470. , updatedAtAttr = this.Model._timestampAttributes.updatedAt
  471. , values = {}
  472. if (countOrOptions === undefined) {
  473. countOrOptions = { by: 1, transaction: null }
  474. } else if (typeof countOrOptions === 'number') {
  475. countOrOptions = { by: countOrOptions, transaction: null }
  476. }
  477. countOrOptions = Utils._.extend({
  478. by: 1,
  479. attributes: {}
  480. }, countOrOptions)
  481. if (Utils._.isString(fields)) {
  482. values[fields] = countOrOptions.by
  483. } else if (Utils._.isArray(fields)) {
  484. Utils._.each(fields, function (field) {
  485. values[field] = countOrOptions.by
  486. })
  487. } else { // Assume fields is key-value pairs
  488. values = fields
  489. }
  490. if (updatedAtAttr && !values[updatedAtAttr]) {
  491. countOrOptions.attributes[updatedAtAttr] = Utils.now(this.daoFactory.daoFactoryManager.sequelize.options.dialect)
  492. }
  493. return this.QueryInterface.increment(this, this.QueryInterface.QueryGenerator.addSchema(this.__factory.tableName, this.__factory.options.schema), values, identifier, countOrOptions)
  494. }
  495. DAO.prototype.decrement = function (fields, countOrOptions) {
  496. Utils.validateParameter(countOrOptions, Object, {
  497. optional: true,
  498. deprecated: 'number',
  499. deprecationWarning: "Decrement expects an object as second parameter. Please pass the decrementor as option! ~> instance.decrement(" + JSON.stringify(fields) + ", { by: " + countOrOptions + " })"
  500. })
  501. if (countOrOptions === undefined) {
  502. countOrOptions = { by: 1, transaction: null }
  503. } else if (typeof countOrOptions === 'number') {
  504. countOrOptions = { by: countOrOptions, transaction: null }
  505. }
  506. if (countOrOptions.by === undefined) {
  507. countOrOptions.by = 1
  508. }
  509. if (!Utils._.isString(fields) && !Utils._.isArray(fields)) { // Assume fields is key-value pairs
  510. Utils._.each(fields, function (value, field) {
  511. fields[field] = -value
  512. })
  513. }
  514. countOrOptions.by = 0 - countOrOptions.by
  515. return this.increment(fields, countOrOptions)
  516. }
  517. DAO.prototype.equals = function(other) {
  518. var result = true
  519. Utils._.each(this.dataValues, function(value, key) {
  520. if(Utils._.isDate(value) && Utils._.isDate(other[key])) {
  521. result = result && (value.getTime() == other[key].getTime())
  522. } else {
  523. result = result && (value == other[key])
  524. }
  525. })
  526. return result
  527. }
  528. DAO.prototype.equalsOneOf = function(others) {
  529. var result = false
  530. , self = this
  531. others.forEach(function(other) { result = result || self.equals(other) })
  532. return result
  533. }
  534. DAO.prototype.setValidators = function(attribute, validators) {
  535. this.validators[attribute] = validators
  536. }
  537. DAO.prototype.toJSON = function() {
  538. return this.get();
  539. }
  540. // private
  541. var initValues = function(values, options) {
  542. // set id to null if not passed as value, a newly created dao has no id
  543. var defaults = this.hasPrimaryKeys ? {} : { id: null },
  544. key;
  545. values = values && _.clone(values) || {}
  546. if (options.isNewRecord) {
  547. if (this.hasDefaultValues) {
  548. Utils._.each(this.defaultValues, function(valueFn, key) {
  549. if (!defaults.hasOwnProperty(key)) {
  550. defaults[key] = valueFn()
  551. }
  552. })
  553. }
  554. if (this.Model._timestampAttributes.createdAt && defaults[this.Model._timestampAttributes.createdAt]) {
  555. this.dataValues[this.Model._timestampAttributes.createdAt] = Utils.toDefaultValue(defaults[this.Model._timestampAttributes.createdAt]);
  556. delete defaults[this.Model._timestampAttributes.createdAt];
  557. }
  558. if (this.Model._timestampAttributes.updatedAt && defaults[this.Model._timestampAttributes.updatedAt]) {
  559. this.dataValues[this.Model._timestampAttributes.updatedAt] = Utils.toDefaultValue(defaults[this.Model._timestampAttributes.updatedAt]);
  560. delete defaults[this.Model._timestampAttributes.updatedAt];
  561. }
  562. if (this.Model._timestampAttributes.createdAt && defaults[this.Model._timestampAttributes.deletedAt]) {
  563. this.dataValues[this.Model._timestampAttributes.deletedAt] = Utils.toDefaultValue(defaults[this.Model._timestampAttributes.deletedAt]);
  564. delete defaults[this.Model._timestampAttributes.deletedAt];
  565. }
  566. }
  567. if (Object.keys(defaults).length) {
  568. for (key in defaults) {
  569. if (!values.hasOwnProperty(key)) {
  570. values[key] = Utils.toDefaultValue(defaults[key])
  571. }
  572. }
  573. }
  574. this.set(values, options)
  575. }
  576. return DAO
  577. })()