UNPKG

tabel

Version:

A simple orm for PostgreSQL which works with simple javascript objects and arrays

168 lines (137 loc) 4.58 kB
const {assign, isArray} = require('lodash'); const Relation = require('./Relation'); const MorphTo = require('./MorphTo'); class MorphMany extends Relation { constructor(ownerTable, toTable, inverse) { if (!(inverse instanceof MorphTo)) { throw new Error('inverse should be a MorphTo relation'); } super(ownerTable); assign(this, {fromTable: ownerTable.fork(), toTable, inverse}); } initRelation(fromModels) { return fromModels.map((m) => assign(m, {[this.relationName]: []})); } getRelated(...args) { if (args.length === 0) { if (this.activeModel !== null) { return this.getRelated([this.activeModel]); } else { return Promise.resolve([]); } } const [fromModels] = args; const {fromTable, inverse} = this; const toTable = this.constraints.apply(this.toTable.fork()); const {foreignKey, typeField} = inverse; const typeValue = fromTable.tableName(); return toTable.where({[typeField]: typeValue}) .whereIn(foreignKey, fromModels.map((m) => m[fromTable.key()])) .all() ; } matchModels(fromModels=[], relatedModels=[]) { const {relationName, fromTable, inverse} = this; const {foreignKey} = inverse; const keyDict = relatedModels.reduce((dict, m) => { const key = m[foreignKey]; if (!isArray(dict[key])) { return assign(dict, {[key]: [m]}); } else { return assign(dict, {[key]: dict[key].concat(m)}); } }, {}); return fromModels.map((m) => assign(m, { [relationName]: isArray(keyDict[m[fromTable.key()]]) ? keyDict[m[fromTable.key()]] : [] })); } insert(...args) { if (args.length === 0) { throw new Error('bad method call'); } if (args.length === 1) { return this.insert(this.activeModel, ...args); } const [fromModel, values] = args; const {fromTable, toTable, inverse} = this; const {foreignKey, typeField} = inverse; return toTable.insert((() => { if (isArray(values)) { return values.map((v) => assign(v, { [foreignKey]: fromModel[fromTable.key()], [typeField]: fromTable.tableName() })); } else { return assign(values, { [foreignKey]: fromModel[this.key], [typeField]: fromTable.tableName() }); } })()); } update(...args) { if (args.length === 0) { throw new Error('bad method call'); } if (args.length === 1) { return this.update(this.activeModel, ...args); } const [fromModel, values] = args; const {fromTable, toTable, inverse} = this; const {foreignKey, typeField} = inverse; return this.constraints.apply(toTable.fork()) .where(typeField, fromTable.tableName()) .where(foreignKey, fromModel[fromTable.key()]) .update(assign(values, { [foreignKey]: fromModel[fromTable.key()], [typeField]: fromTable.tableName() })); } del(...args) { if (args.length === 0) { return this.del(this.activeModel); } const [fromModel] = args; const {fromTable, toTable, inverse} = this; const {foreignKey, typeField} = inverse; return this.constraints.apply(toTable.fork()) .where(typeField, fromTable.tableName()) .where(foreignKey, fromModel[fromTable.key()]) .del() ; } join(joiner=(() => {}), label=null) { label = this.jointLabel(label, {}); const {fromTable, toTable, inverse} = this; const {foreignKey, typeField} = inverse; if (this.ownerTable.scopeTrack.hasJoint(label)) { return this.ownerTable; } else { return this.ownerTable.joint((q) => { q.join(toTable.tableName(), (j) => { j.on(toTable.c(typeField), '=', fromTable.orm.raw('?', [fromTable.tableName()])) .on(toTable.c(foreignKey), '=', fromTable.keyCol()); joiner(j); }); }, label); } } leftJoin(joiner=(() => {}), label=null) { label = this.jointLabel(label, {isLeftJoin: true}); const {fromTable, toTable, inverse} = this; const {foreignKey, typeField} = inverse; if (this.ownerTable.scopeTrackhasJoint(label)) { return this.ownerTable; } else { return this.ownerTable.joint((q) => { q.leftJoin(toTable.tableName(), (j) => { j.on(toTable.c(typeField), '=', fromTable.orm.raw('?', [fromTable.tableName()])) .on(toTable.c(foreignKey), '=', fromTable.keyCol()); joiner(j); }); }, label); } } } module.exports = MorphMany;