cheetah-framework
Version:
Cheetah Framework JS used in all our applications
140 lines (111 loc) • 3.76 kB
JavaScript
class Model {
constructor (data = null) {
this.uid = getUid()
Object.defineProperty(this, '_attributes', {
value: {},
writable: true,
enumerable: true,
configurable: true
})
this._postMutators = [...this.constructor.defaultPostMutators, ...this.constructor.postMutators]
/**
* LARAVEL ACCESSORS & MUTATORS
* To use it, define a function in the Model
* following the Laravel naming convention
* https://laravel.com/docs/master/eloquent-mutators
*
* If you need to have access to properties in your mutator,
* you can make it a post mutator by adding it to the postMutators array
*/
this.defineMutators()
const values = _.defaultsDeep(data ? _.cloneDeep(data) : data, this.defaultValue)
_.extend(
this,
_.omit(
values,
['_attributes', 'uid', '_postMutators', ...this._postMutators]
)
)
this.defineMutators(true)
_.extend(this, _.pick(values, this._postMutators))
}
/**
* Do not override in model, use postMutators getter instead
* This exists to allow other classes to add post mutators (ex: StateHandler)
*/
static defaultPostMutators = []
static _cachedMutators = null
static _cachedPostMutators = null
static get postMutators () {
return []
}
getMutatorMethods (post) {
const cachedMutatorsVar = post ? '_cachedMutators' : '_cachedPostMutators'
if (this.constructor[cachedMutatorsVar]) {
return this.constructor[cachedMutatorsVar]
}
const properties = Object.getOwnPropertyNames(Object.getPrototypeOf(this))
.filter(prop => prop !== 'constructor')
/**
* Return an object
* the key's of the object is set to the attributes name
* and it contains objects with the type as a key and the method as a value
* eg: { name:{ 'set': 'setNameAttribute', 'get': 'getNameAttribute' } }
*/
this.constructor[cachedMutatorsVar] = _.reduce(properties, (methods, value) => {
const information = /^(set|get)(.*)Attribute$/.exec(value)
if (information) {
const attribute = _.snakeCase(information[2])
const isPostMutator = this._postMutators.includes(attribute)
if (!post && isPostMutator) {
return methods
} else if (post && !isPostMutator) {
return methods
}
if (!methods[attribute]) {
methods[attribute] = {}
}
methods[attribute][information[1]] = information[0]
}
return methods
}, {})
return this.constructor[cachedMutatorsVar]
}
defineMutators (post = false) {
const mutators = this.getMutatorMethods(post)
_.each(mutators, (mutator, attributeName) => {
// Setter and getter to retrieve Accessors and/or set Mutators
Object.defineProperty(this, attributeName, {
enumerable: true,
get: mutator['get']
? () => this[mutator['get']](this._attributes[attributeName])
: () => this._attributes[attributeName],
set: mutator['set']
? (newValue, oldValue) => { this[mutator['set']](newValue, oldValue) }
: newValue => { this._attributes[attributeName] = newValue }
})
})
}
serializeData () {
return JSON.parse(JSON.stringify(this))
}
toJSON () {
return _.omit(this, ['_attributes', '_postMutators', 'uid', 'notification'])
}
get defaultValue () {
return {}
}
}
function TranslatedFieldValue (defaultValue) {
const translated = {}
_.each(Cheetah.contentLanguages, langKey => {
translated[langKey] = defaultValue || ''
})
return translated
}
let uidCount = 0
function getUid () {
return ++uidCount
}
export default Model
export { Model, TranslatedFieldValue }