From 7e6f45e9a13d1cf294471b3df8ceff4eee40358a Mon Sep 17 00:00:00 2001 From: CanRau Date: Wed, 23 Oct 2019 15:47:09 -0500 Subject: [PATCH 1/4] docs: fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c61e543..2ffe970 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ whereas the options are listed here (with default value). /* By default sequelize-temporal persist only changes, and saves the previous state in the history table. The "full" option saves all transactions into the temporal database (i.e. this includes the latest state.) - This allows to only query the hostory table to get the full history of an entity. + This allows to only query the history table to get the full history of an entity. */ full: false ``` From 369551d94ea16d1e5913f4e44912a2a43755d3e1 Mon Sep 17 00:00:00 2001 From: CanRau Date: Wed, 23 Oct 2019 15:49:25 -0500 Subject: [PATCH 2/4] feat: add excludeFields option --- README.md | 4 +++- index.js | 31 +++++++++++++++++++++---------- test/test.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 2ffe970..f04e0b2 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,9 @@ whereas the options are listed here (with default value). (i.e. this includes the latest state.) This allows to only query the history table to get the full history of an entity. */ - full: false + full: false, + /* All fields will be saved to history. Add field names to exclude from history. */ + excludeFields: [], ``` Details diff --git a/index.js b/index.js index a0dbfe6..edd9ae0 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,8 @@ var temporalDefaultOptions = { // runs the insert within the sequelize hook chain, disable // for increased performance blocking: true, - full: false + full: false, + excludeFields: [], }; var excludeAttributes = function(obj, attrsToExclude){ @@ -36,15 +37,25 @@ var Temporal = function(model, sequelize, temporalOptions){ }; var excludedAttributes = ["Model","unique","primaryKey","autoIncrement", "set", "get", "_modelAttribute"]; - var historyAttributes = _(model.rawAttributes).mapValues(function(v){ - v = excludeAttributes(v, excludedAttributes); - // remove the "NOW" defaultValue for the default timestamps - // we want to save them, but just a copy from our master record - if(v.fieldName == "createdAt" || v.fieldName == "updatedAt"){ - v.type = Sequelize.DATE; - } - return v; - }).assign(historyOwnAttrs).value(); + var historyAttributes = _(model.rawAttributes) + .filter(function(v) { + if ( + temporalOptions.excludeFields.length && + temporalOptions.excludeFields.includes(v.fieldName) + ) { + return false + } + return true + }) + .mapValues(function(v){ + v = excludeAttributes(v, excludedAttributes); + // remove the "NOW" defaultValue for the default timestamps + // we want to save them, but just a copy from our master record + if(v.fieldName == "createdAt" || v.fieldName == "updatedAt"){ + v.type = Sequelize.DATE; + } + return v; + }).assign(historyOwnAttrs).value(); // If the order matters, use this: //historyAttributes = _.assign({}, historyOwnAttrs, historyAttributes); diff --git a/test/test.js b/test/test.js index 0a7bc5c..bb8cf02 100644 --- a/test/test.js +++ b/test/test.js @@ -35,6 +35,20 @@ describe('Read-only API', function(){ return sequelize.sync({ force: true }); } + function freshDBWithExcludedFields() { + sequelize = new Sequelize('', '', '', { + dialect: 'sqlite', + storage: __dirname + '/.test.sqlite' + }); + User = Temporal(sequelize.define('User', { + name: Sequelize.TEXT, + fieldToExclude: Sequelize.TEXT, + }, { paranoid: true }), sequelize, { excludeFields: ['fieldToExclude'] }); + UserHistory = sequelize.models.UserHistory; + + return sequelize.sync({ force: true }); + } + function assertCount(modelHistory, n, opts){ // wrapped, chainable promise return function(obj){ @@ -332,4 +346,25 @@ describe('Read-only API', function(){ }); + describe('exclude fields option', function() { + + beforeEach(freshDBWithExcludedFields); + + it('onUpdate/onDestroy: shouldn\'t store excluded felds' , function(){ + return User.create() + .then(assertCount(UserHistory,0)) + .then(function(user){ + user.name = "foo"; + return user.save(); + }).then(function(histories) { + assertCount(UserHistory,1)(histories) + assert.equal(histories[0].fieldToExclude, null, 'fieldToExclude null') + }) + .then(function(user){ + return user.destroy(); + }).then(assertCount(UserHistory,2)) + }); + + }) + }); From a755c26edb145f51f3dbb264829173af626b7ba6 Mon Sep 17 00:00:00 2001 From: CanRau Date: Wed, 25 Dec 2019 18:35:11 -0500 Subject: [PATCH 3/4] fix: use reduce instead of filter & map --- index.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index edd9ae0..3e46186 100644 --- a/index.js +++ b/index.js @@ -37,27 +37,27 @@ var Temporal = function(model, sequelize, temporalOptions){ }; var excludedAttributes = ["Model","unique","primaryKey","autoIncrement", "set", "get", "_modelAttribute"]; - var historyAttributes = _(model.rawAttributes) - .filter(function(v) { + + var historyAttributes = _.reduce(_.keys(model.rawAttributes), function(acc, key) { + var v = excludeAttributes(model.rawAttributes[key], excludedAttributes); + // drop excluded fields if ( - temporalOptions.excludeFields.length && + temporalOptions.excludeFields.length && temporalOptions.excludeFields.includes(v.fieldName) ) { - return false + return acc } - return true - }) - .mapValues(function(v){ - v = excludeAttributes(v, excludedAttributes); + // remove the "NOW" defaultValue for the default timestamps // we want to save them, but just a copy from our master record if(v.fieldName == "createdAt" || v.fieldName == "updatedAt"){ v.type = Sequelize.DATE; } - return v; - }).assign(historyOwnAttrs).value(); - // If the order matters, use this: - //historyAttributes = _.assign({}, historyOwnAttrs, historyAttributes); + + acc[key] = v + return acc + }, {}) + historyAttributes = _.assign({}, historyOwnAttrs, historyAttributes); var historyOwnOptions = { timestamps: false From 3ae042bd4411e1e5471a1a592c2b80ac6362eeb3 Mon Sep 17 00:00:00 2001 From: CanRau Date: Wed, 25 Dec 2019 18:36:19 -0500 Subject: [PATCH 4/4] test: query history before accessing --- test/test.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/test.js b/test/test.js index bb8cf02..8ce3eab 100644 --- a/test/test.js +++ b/test/test.js @@ -350,19 +350,20 @@ describe('Read-only API', function(){ beforeEach(freshDBWithExcludedFields); - it('onUpdate/onDestroy: shouldn\'t store excluded felds' , function(){ + it('onUpdate/onDestroy: shouldn\'t store excluded fields' , function(){ return User.create() .then(assertCount(UserHistory,0)) .then(function(user){ user.name = "foo"; return user.save(); - }).then(function(histories) { - assertCount(UserHistory,1)(histories) + }) + .then(function() { + return UserHistory.findAll(); + }) + .then(function(histories) { + assertCount(UserHistory, 1)(histories) assert.equal(histories[0].fieldToExclude, null, 'fieldToExclude null') }) - .then(function(user){ - return user.destroy(); - }).then(assertCount(UserHistory,2)) }); })