Last active
January 24, 2020 18:47
-
-
Save ratulSharker/44798d1d59d6c729030fa3f24da4b2ca to your computer and use it in GitHub Desktop.
JS Data model difference calculator.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Base model | |
function BaseModel() { | |
} | |
BaseModel.prototype.difference = function(latestModel, arrDiffActual = false) { | |
const difference = {}; | |
const self = this; | |
Object.keys(this).forEach( function(key) { | |
if(self[key] instanceof BaseModel) { | |
// kind of another base model | |
const keyValueDifference = self[key].difference(latestModel[key]); | |
if(Object.keys(keyValueDifference).length > 0) { | |
difference[key] = keyValueDifference; | |
} | |
} else if(Array.isArray(self[key])) { | |
// item is type of array | |
const diffArr = self.arrDifference(self[key], latestModel[key], arrDiffActual); | |
if(diffArr !== null) { | |
difference[key] = diffArr; | |
} | |
} | |
else { | |
// basic type | |
if(self[key] !== latestModel[key]) { | |
difference[key] = latestModel[key]; | |
} | |
} | |
}); | |
return difference; | |
} | |
// Array items supported features. | |
// 1. Supports heterogenus array. | |
// 2. Array of different length is considered different. | |
// 3. If array item is placed at different position, it can be considered two ways | |
// 3.1 The whole array is changed. | |
// 3.2 Only those items are changed, where item do not match at specified position. | |
// the behaviour in #3 can be controlled using `actualDiff`. | |
BaseModel.prototype.arrDifference = function(origArr, newArr, actualDiff) { | |
if(origArr.length !== newArr.length) { | |
return newArr; | |
} else { | |
// now loop through each array element | |
const diffArr = [] | |
for(let index = 0; index < origArr.length; index++) { | |
if(origArr[index] instanceof BaseModel) { | |
// item is type of base model | |
const keyValueDifference = origArr[index].difference(newArr[index]); | |
if(Object.keys(keyValueDifference).length > 0) { | |
diffArr.push(keyValueDifference); | |
} | |
} else if(Array.isArray(origArr[index])) { | |
// item is type of array | |
const difference = this.arrDifference(origArr[index], newArr[index], actualDiff); | |
if(difference !== null) { | |
diffArr.push(difference); | |
} | |
} else { | |
// basic type | |
if(origArr[index] !== newArr[index]) { | |
diffArr.push(newArr[index]); | |
} | |
} | |
} | |
if(actualDiff) { | |
return diffArr.length > 0 ? diffArr : null; | |
} else { | |
return diffArr.length > 0 ? newArr : null; | |
} | |
} | |
} | |
// Submodel user | |
function User (firstname, lastname, status, devices) { | |
BaseModel.call(this); | |
this.firstname = firstname; | |
this.lastname = lastname; | |
this.status = status; | |
this.devices = devices; | |
} | |
User.prototype = BaseModel.prototype; | |
// Submodel user status | |
function UserStatus (id, name) { | |
BaseModel.call(this); | |
this.id = id; | |
this.name = name; | |
} | |
UserStatus.prototype = BaseModel.prototype; | |
// Submodel device | |
function Device(id, type, name) { | |
BaseModel.call(this); | |
this.id = id; | |
this.type = type; | |
this.name = name; | |
} | |
Device.prototype = BaseModel.prototype; | |
const iPhone5 = new Device(1, "mobile", "iphone 5"); | |
const macbook = new Device(2, "laptop", "Macbook pro 2015"); | |
const smartwatch = new Device(3, "smartwatch", "Smartwatch 3"); | |
const ratul = new User("Ratul", "sharker", new UserStatus(1, "ACTIVE"), [iPhone5, macbook]); | |
const ratulChanged = new User("Ratul", "dorker", new UserStatus(2, "INACTIVE"), [iPhone5, smartwatch]); | |
console.log(ratul.difference(ratulChanged, false)); | |
function MultiLevelArrModel(arr) { | |
BaseModel.call(this); | |
this.arr = arr; | |
} | |
MultiLevelArrModel.prototype = BaseModel.prototype; | |
const mLvlArr = new MultiLevelArrModel([[1, 2, 3], [3, 4]]); | |
const mLvlArrChanged = new MultiLevelArrModel([[1, 2, 3], [4, 3]]); | |
console.log(mLvlArr.difference(mLvlArrChanged, true)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment