I'm attempting to create an extensible base model class that will allow for diffing between original
and attributes
so that I can create a getDirty()
method on the child class that will diff between the objects orignal
properties and any changed attributes
. Here's the class so far:
import Vue from 'vue'
class Model {
constructor (attributes) {
this.original = attributes
this.attributes = attributes
Object.keys(this.attributes).forEach((property) => {
Object.defineProperty(this, property, {
get: () => this.getAttribute(property),
set: (value) => this.setAttribute(property, value)
})
})
}
getAttribute (key) {
return this.attributes[key]
}
setAttribute (key, value) {
this.attributes[key] = value
}
static fetchById (id) {
if (!id) {
throw new Error('Cannot fetch without id')
}
return Vue.prototype.$http
.get(this.endpoint + id)
.then(response => {
return new this(response.data)
})
.catch(error => {
console.error(error)
})
}
}
export default Model
With this code, I am creating an account by extending this Model with an Account model:
import Model from './Model'
import Vue from 'vue'
class Account extends Model {
static endpoint = '/api/accounts/'
getOwner () {
if (this.company_owner_uuid) {
return 'company'
}
return 'person'
}
getDirty = () => {
// This log is showing the changed name from the component input, rather than the original
console.log(this.original.person_owner.first_name)
const diff = Object.keys(this.original).reduce((diff, key) => {
if (this.attributes[key] === this.original[key]) return diff
return {
...diff,
[key]: this.original[key]
}
}, {})
return diff
}
update () {
return Vue.prototype.$http
.put(`${Account.endpoint}/${this.account_uuid}`, this.getDirty())
.then(response => {
console.log(response)
return response.data
})
.catch(error => {
console.error(error)
})
}
}
export default Account
And in my component:
Account.fetchById(this.id).then(account => {
this.account = account
})
.catch(error => {
console.error(error)
})
.then(() => {
// hide loading or whatever after promise is fully resolved...
})
This all works really so far aside from when I make a change to the account, it mutates both this.original
and this.attributes
. Does anyone have a recommendation for creating an immutable this.original
version of the account object that is passed into the constructor that could then be used for comparison to the mutated attributes
? My end goal here is to only send any modified attributes to the back-end (I'm using Laravel 5.8). Thanks!