Skip to content

Instantly share code, notes, and snippets.

@thecaddy
Last active September 23, 2021 06:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thecaddy/b72a062b62b835fa06a8 to your computer and use it in GitHub Desktop.
Save thecaddy/b72a062b62b835fa06a8 to your computer and use it in GitHub Desktop.
A sequelize plugin to support postgres inherited tables with models
//THIS MODEL INHERITS FROM THE OTHER TABLE
import inheritFrom form './inheritFrom'
import inherittedModel from './inherittedModel'
export default function(sequelize, DataTypes) {
const ChildModel = inheritFrom(sequelize, DataTypes)('childModel', inherittedModel, {
// define child model specific properties here
id: Sequelize.INTEGER,
some_model_id: Sequelize.INTEGER
}, {
hooks: {
beforeDestroy(instance, options) {
return instance.sequelize.models.someModel({
where: {
id: instance.some_model_id
}
})
},
classMethods: {
associate: function (models) {
const {someModel} = models;
this.belongsTo(someModel)
}
},
instanceMethods: {
anInstanceMethod(){}
},
});
return ChildModel;
};
const _merge = (base, attach) => {
if (typeof attach === 'object') {
const keys = Object.keys(attach)
for (let i = 0; i < keys.length; i++) {
if (!base[keys[i]]) {
base[keys[i]] = attach[keys[i]];
} else {
base[keys[i]] = _merge(base[keys[i]], attach[keys[i]]);
}
}
} else if (typeof base === 'function'
&& typeof attach === 'function') {
return function(...args) {
const temp = base.apply(this, args);
if (temp) {
return Promise.resolve(temp)
.then(() => attach.apply(this, args))
} else {
attach.apply(this, args)
}
}
} else {
throw new Error('CANNOT MERGE', base, attach)
}
return base
}
const merge = (base, ...args) => {
for(let i = 0, len = args.length; i < len; i++) {
if(typeof args[i] === 'object') {
base = _merge(base, args[i])
}
}
return base
}
export default (sequelize, DataTypes) => {
const _sequelize = sequelize;
const _DataTypes = DataTypes;
return (name, base, defs, opts) => {
const {definition, options} = base(_sequelize, _DataTypes);
const {associate} = options.classMethods;
const def = merge(definition, defs);
// const opt = _.merge(options, opts);
const opt = merge(opts, options);
return _sequelize.define(name, def, opt);
};
};
//THIS IS THE MODEL TO BE INHERITED FROM
//THIS SHOULD NOT BE IMPORTED BY SEQUELIZE
export default function(sequelize, Sequelize) {
return {
definition: {
// define inheritted model properties to be inheritted here
id: Sequelize.INTEGER,
related_model_id: Sequelize.INTEGER
},
options: {
//hooks always return promises
hooks: {
beforeDestroy(instance, option) {
return instance.models.anotherModel.destroy({
where: {
id: instance.related_model_id
}
})
}
},
classMethods: {
//association relies on context, not pass in models
associate: function(){
const {models} = this.sequelize
this.belongsTo(models.anotherModel)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment