lux-framework
Version:
Build scalable, Node.js-powered REST APIs with almost no code.
190 lines (169 loc) • 3.94 kB
JavaScript
// @flow
import type { Model } from '../../index';
import type { Relationship$opts } from '../interfaces';
type Params = {
record: Model;
value: ?Model | Array<Model>;
opts: Relationship$opts;
trx: Object;
};
function updateHasOne({
record,
value,
opts,
trx
}: Params): Array<Object> {
const recordPrimaryKey = record.getPrimaryKey();
if (value) {
if (value instanceof opts.model) {
return [
opts.model
.table()
.transacting(trx)
.update(opts.foreignKey, null)
.where(
`${opts.model.tableName}.${opts.foreignKey}`,
recordPrimaryKey
)
.whereNot(
`${opts.model.tableName}.${opts.model.primaryKey}`,
value.getPrimaryKey()
),
opts.model
.table()
.transacting(trx)
.update(opts.foreignKey, recordPrimaryKey)
.where(
`${opts.model.tableName}.${opts.model.primaryKey}`,
value.getPrimaryKey()
)
];
}
} else {
return [
opts.model
.table()
.transacting(trx)
.update(opts.foreignKey, null)
.where(
`${opts.model.tableName}.${opts.foreignKey}`,
recordPrimaryKey
)
];
}
return [];
}
function updateHasMany({
record,
value,
opts,
trx
}: Params): Array<Object> {
const recordPrimaryKey = record.getPrimaryKey();
if (Array.isArray(value) && value.length) {
return [
opts.model
.table()
.transacting(trx)
.update(opts.foreignKey, null)
.where(
`${opts.model.tableName}.${opts.foreignKey}`,
recordPrimaryKey
)
.whereNotIn(
`${opts.model.tableName}.${opts.model.primaryKey}`,
value.map(item => item.getPrimaryKey())
),
opts.model
.table()
.transacting(trx)
.update(opts.foreignKey, recordPrimaryKey)
.whereIn(
`${opts.model.tableName}.${opts.model.primaryKey}`,
value.map(item => item.getPrimaryKey())
)
];
}
return [
opts.model
.table()
.transacting(trx)
.update(opts.foreignKey, null)
.where(
`${opts.model.tableName}.${opts.foreignKey}`,
recordPrimaryKey
)
];
}
function updateBelongsTo({
record,
value,
opts,
trx
}: Params): Array<Object> {
if (value instanceof opts.model) {
const inverseOpts = opts.model.relationshipFor(opts.inverse);
const foreignKeyValue = value.getPrimaryKey();
Reflect.set(record, opts.foreignKey, foreignKeyValue);
if (inverseOpts && inverseOpts.type === 'hasOne') {
return [
record.constructor
.table()
.transacting(trx)
.update(opts.foreignKey, null)
.where(opts.foreignKey, foreignKeyValue)
.whereNot(
`${record.constructor.tableName}.${record.constructor.primaryKey}`,
record.getPrimaryKey()
)
];
}
}
return [];
}
/**
* @private
*/
export default function updateRelationship(
record: Model,
name: string,
trx: Object
): Array<Object> {
const opts = record.constructor.relationshipFor(name);
if (!opts) {
const {
constructor: {
name: className
}
} = record;
throw new Error(`Could not find relationship '${name} on '${className}`);
}
const { dirtyRelationships } = record;
if (!dirtyRelationships.has(name)) {
return [];
}
const value = dirtyRelationships.get(name);
switch (opts.type) {
case 'hasOne':
return updateHasOne({
record,
value,
opts,
trx
});
case 'hasMany':
return updateHasMany({
record,
value,
opts,
trx
});
default:
return updateBelongsTo({
record,
value,
opts,
trx
});
}
}