@@ -13,6 +13,9 @@ function changed(Model, options) {
1313
1414 var loopback = require ( 'loopback' ) ;
1515
16+ /**
17+ * Determine which properties are changed and store them in changedItems
18+ */
1619 Model . observe ( 'before save' , function ( ctx , next ) {
1720 // Do nothing if a new instance if being created.
1821 if ( ctx . instance && ctx . isNewInstance ) {
@@ -32,48 +35,65 @@ function changed(Model, options) {
3235
3336 if ( ctx . currentInstance ) {
3437 debug ( 'Detected prototype.updateAttributes' ) ;
35- if ( Model . propertiesChanged ( ctx . currentInstance , ctx . data , properties ) ) {
36- ctx . hookState . changedItems = [ ctx . currentInstance . getId ( ) ] ;
37- }
38+ //if (Model.propertiesChanged(ctx.currentInstance, ctx.data, properties)) {
39+ // ctx.hookState.changedItems = [ctx.currentInstance.getId()];
40+ //}
41+ ctx . hookState . changedItems = Model . getChangedProperties ( ctx . currentInstance , ctx . data , properties ) ;
42+
43+ //console.log('ctx.hookState.changedItems 1 a: ');
44+ //console.log(ctx.hookState.changedItems);
45+
3846 next ( ) ;
3947 } else if ( ctx . instance ) {
4048 debug ( 'Working with existing instance %o' , ctx . instance ) ;
4149 // Figure out wether this item has changed properties.
4250 ctx . instance . itemHasChangedProperties ( ctx . instance , properties )
4351 . then ( function ( changed ) {
44- if ( changed ) {
45- ctx . hookState . changedItems = [ ctx . instance . getId ( ) ] ;
46- }
52+ ctx . hookState . changedItems = changed ;
4753 next ( ) ;
4854 } ) . catch ( next ) ;
4955 } else {
5056 debug ( 'anything else: upsert, updateAll' ) ;
5157 // Figure out which items have changed properties.
5258 Model . itemsWithChangedProperties ( ctx . where , ctx . data , properties )
53- . then ( function ( items ) {
54- debug ( 'items: %o' , ctx . items ) ;
55- if ( items && items . length ) {
56- ctx . hookState . changedItems = items ;
57- }
59+ . then ( function ( changed ) {
60+ ctx . hookState . changedItems = changed ;
5861 next ( ) ;
5962 } ) . catch ( next ) ;
6063 }
6164 } ) ;
6265
6366 Model . observe ( 'after save' , function ( ctx , next ) {
64- if ( ctx . hookState . changedItems && ctx . hookState . changedItems . length ) {
67+ if ( ctx . hookState . changedItems && ! _ . isEmpty ( ctx . hookState . changedItems ) ) {
68+
69+ var changedItems = ctx . hookState . changedItems ;
70+
71+ debug ( 'after save: changedItems: %o' , changedItems ) ;
72+
73+ var idList = Object . keys ( ctx . hookState . changedItems ) ;
74+ debug ( 'after save: idList: %o' , idList ) ;
75+
6576 Model . find ( {
6677 where : {
6778 id : {
68- inq : ctx . hookState . changedItems
79+ inq : idList
6980 }
7081 } ,
7182 fields : [
7283 Model . getIdName ( )
7384 ]
7485 } ) . then ( function ( items ) {
86+ // Extract the ID's from the resultset
87+ var itemIds = Model . extractChangedItemIds ( items ) ;
88+ debug ( 'after save: itemIds' , itemIds ) ;
89+
90+ // TODO remove changedItems keys that are not in itemIds
91+ var callbackItems = changedItems ;
92+
93+ debug ( 'after save: callbackItems' , callbackItems ) ;
94+
7595 if ( typeof Model [ options . callback ] !== 'function' ) return false ;
76- return Model [ options . callback ] ( Model . extractChangedItemIds ( items ) ) ;
96+ return Model [ options . callback ] ( callbackItems ) ;
7797 } )
7898 . then ( function ( res ) {
7999 next ( ) ;
@@ -92,29 +112,38 @@ function changed(Model, options) {
92112 * @returns {Array } Returns a list of Model instance Ids whose data differ from
93113 * that in the properties argument.
94114 */
95- Model . itemsWithChangedProperties = function ( conditions , target , properties , cb ) {
96- debug ( 'Looking for items with changed properties...' ) ;
97- debug ( 'conditions is: %o' , conditions ) ;
98- debug ( 'target is: %o' , target ) ;
99- debug ( 'properties is: %o' , properties ) ;
115+ Model . itemsWithChangedProperties = function ( conditions , newVals , properties , cb ) {
116+ debug ( 'itemsWithChangedProperties: Looking for items with changed properties...' ) ;
117+ debug ( 'itemsWithChangedProperties: conditions is: %o' , conditions ) ;
118+ debug ( 'itemsWithChangedProperties: newVals is: %o' , newVals ) ;
119+ debug ( 'itemsWithChangedProperties: properties is 1 : %o' , properties ) ;
100120 cb = cb || utils . createPromiseCallback ( ) ;
101121
102122 conditions = conditions || { } ;
103- target = typeof target . toJSON === 'function' ? target . toJSON ( ) : target || { } ;
123+ newVals = typeof newVals . toJSON === 'function' ? newVals . toJSON ( ) : newVals || { } ;
104124 properties = properties || { } ;
105125
126+ var filterFields = [
127+ Model . getIdName ( )
128+ ] ;
129+
106130 // Build up a list of property conditions to include in the query.
107- var fields = { or : [ ] } ;
108- _ . forEach ( target , function ( value , key ) {
131+ var propertyConditions = { or : [ ] } ;
132+ _ . forEach ( newVals , function ( value , key ) {
109133 if ( _ . includes ( properties , key ) ) {
110134 var fieldFilter = { } ;
111135 fieldFilter [ key ] = { 'neq' : value } ;
112- fields . or . push ( fieldFilter ) ;
136+ propertyConditions . or . push ( fieldFilter ) ;
137+ filterFields . push ( key ) ;
113138 }
114139 } ) ;
115140
141+ if ( ! propertyConditions . or . length ) propertyConditions = { } ;
142+
143+ debug ( 'itemsWithChangedProperties: propertyConditions 1 : %o' , propertyConditions ) ;
144+
116145 // If there are no property conditions, do nothing.
117- if ( _ . isEmpty ( properties ) ) {
146+ if ( _ . isEmpty ( propertyConditions ) ) {
118147 process . nextTick ( function ( ) {
119148 cb ( null , false ) ;
120149 } ) ;
@@ -123,18 +152,63 @@ function changed(Model, options) {
123152
124153 // Build the final filter.
125154 var filter = {
126- fields : [
127- Model . getIdName ( )
128- ] ,
155+ fields : filterFields ,
129156 where : {
130- and : [ fields , conditions ]
157+ and : [ propertyConditions , conditions ]
131158 }
132159 } ;
133- debug ( 'Searching using filter: %s' , JSON . stringify ( filter , null , 4 ) ) ;
160+
161+ debug ( 'itemsWithChangedProperties: propertyConditions 2 : %o' , propertyConditions ) ;
162+ debug ( 'itemsWithChangedProperties: filter Fields %o' , filterFields ) ;
163+ debug ( 'itemsWithChangedProperties: conditions %o' , conditions ) ;
164+ debug ( 'itemsWithChangedProperties: final filter %o' , filter ) ;
165+
134166 Model . find ( filter )
135167 . then ( function ( results ) {
136- debug ( 'Found items that will be changed: %o' , results ) ;
137- cb ( null , Model . extractChangedItemIds ( results ) ) ;
168+
169+ debug ( 'itemsWithChangedProperties: filter results %o' , results ) ;
170+
171+ var changedProperties = { } ;
172+
173+ results . map ( function ( oldVals ) {
174+
175+ debug ( 'itemsWithChangedProperties: oldVals %o' , oldVals ) ;
176+ debug ( 'itemsWithChangedProperties: newVals %o' , newVals ) ;
177+
178+ //changedProperties[oldVals.id] = {};
179+
180+ var changed = { } ;
181+
182+ properties . map ( function ( property ) {
183+
184+ debug ( 'itemsWithChangedProperties: Matching property %s' , property ) ;
185+
186+ if ( newVals [ property ] !== undefined ) {
187+
188+ var newVal = newVals [ property ] ;
189+
190+ debug ( 'itemsWithChangedProperties: - newVal %s : %s : ' , property , newVal ) ;
191+
192+ if ( ! oldVals [ property ] ) {
193+ changed [ property ] = newVal ;
194+ debug ( 'itemsWithChangedProperties: - no oldVal %s : %s : ' , property , newVal ) ;
195+ } else if ( newVal !== oldVals [ property ] ) {
196+ var oldVal = oldVals [ property ] ;
197+ debug ( 'itemsWithChangedProperties: - oldVal %s : %s : ' , property , newVal ) ;
198+
199+ changed [ property ] = newVal ;
200+ }
201+
202+ }
203+ } ) ;
204+
205+ debug ( 'itemsWithChangedProperties: changed %o' , changed ) ;
206+ changedProperties [ oldVals . id ] = changed ;
207+
208+ } ) ;
209+
210+ debug ( 'itemsWithChangedProperties: changedProperties %o' , changedProperties ) ;
211+ cb ( null , changedProperties ) ;
138212 } ) . catch ( cb ) ;
139213
140214 return cb . promise ;
@@ -161,9 +235,9 @@ function changed(Model, options) {
161235
162236 Model . findById ( this . getId ( ) )
163237 . then ( function ( instance ) {
164- var changed = Model . propertiesChanged ( instance , data , properties ) ;
165- debug ( 'found supposedly changed items: %o' , changed ) ;
166- cb ( null , changed ) ;
238+ var changedProperties = Model . getChangedProperties ( instance , data , properties ) ;
239+ debug ( 'itemHasChangedProperties: found supposedly changed items: %o' , changedProperties ) ;
240+ cb ( null , changedProperties ) ;
167241 } ) . catch ( cb ) ;
168242
169243 return cb . promise ;
@@ -191,11 +265,39 @@ function changed(Model, options) {
191265 }
192266 } ) ;
193267 if ( changed ) {
194- debug ( 'properties were changed' ) ;
268+ debug ( 'propertiesChanged: properties were changed' ) ;
195269 }
196270 return changed ;
197271 } ;
198272
273+ Model . getChangedProperties = function ( oldVals , newVals , properties ) {
274+ debug ( 'getChangedProperties: comparing oldVals %o with newVals %o in properties %o' , oldVals , newVals , properties ) ;
275+
276+ var itemId = oldVals [ Model . getIdName ( ) ] ;
277+ var changedProperties = { } ;
278+ changedProperties [ itemId ] = { } ;
279+
280+ _ . forEach ( properties , function ( key ) {
281+ debug ( 'getChangedProperties: - checking property %s ' , key ) ;
282+
283+ if ( newVals [ key ] ) {
284+ var newVal = newVals [ key ] ;
285+ debug ( 'getChangedProperties: - new value %s ' , newVal ) ;
286+
287+ if ( ! oldVals [ key ] || newVal !== oldVals [ key ] ) {
288+ debug ( 'getChangedProperties: - changed or new value %s itemId %s' , newVal , itemId ) ;
289+
290+ changedProperties [ itemId ] [ key ] = newVal ;
291+ }
292+ }
293+ } ) ;
294+ if ( ! _ . isEmpty ( changedProperties [ itemId ] ) ) {
295+ debug ( 'getChangedProperties: Properties were changed %o' , changedProperties ) ;
296+ return changedProperties ;
297+ }
298+ return false ;
299+ } ;
300+
199301 Model . extractChangedItemIds = function ( items ) {
200302 return _ . pluck ( items , Model . getIdName ( ) ) ;
201303 } ;
0 commit comments