TL;DR: Make the decorator set a property in the class and look for it.
While trying my hand at writing an ORM, I had a problem of initialising the database through a dummy instantiation of some models, without running an explicit command. In java, I can use code generation to provide a list of objects following a pattern (e.g. implementing an interface). Here, the concepts are somewhat different and I found out I can use decorators.
My model looks like this:
import { table, field } from '../ngOrm/decorators'
@table({ name: 'LABELS', autoIncrement: true })
export class Tag {
@field({ name: 'label', dbtype: 'TEXT', nullAllowed: false })
label: string
}
where the @table()
and @field
are decorators.
Ideally, I should have a function along the lines:
function setup(): void {
for(let obj in <list of objects decorated with @table>) {
new obj();
}
}
Now, obtaining the list is somewhat difficult since different classes can be in different files all over the place.
Solution
The solution I found is to have the decorator set an obscure property on the decorated object:
export function specialDecorator(item: any) {
item.isSpeciallyDecorated = true
}
and add it to the @table
decorator:
export function table(opts: TableOpts = {}): (target: Function) => void {
specialDecorator(target) // <== here
return (target: Function) => decorateClass(target, opts)
}
Once you have done this, the decorated model will have a property named isSpeciallyDecorated
, which we can look for:
function scanScope(theScope: any) {
for (let prop in theScope) {
if (theScope[prop]['isSpeciallyDecorated']) {
console.log(`Is ${prop} decorated? ${theScope[prop]['isSpeciallyDecorated']}!`)
} else {
console.log(`${prop} is not specially decorated. :-(`)
}
}
}
Now, all we have to do is invoke the function in the right place:
export { Photo } from './photo-model'
export { Tag } from './tag-model'
scanScope(this)
This will print out that our models are specially decorated.
Note: You need to explicitly import/export the models in your file as the call is only local (this
is the current scope).
Member discussion: