Skip to content

Commit

Permalink
fix: empty n:m relationships loads every record instead of an empty a…
Browse files Browse the repository at this point in the history
…rray (#277)
  • Loading branch information
zacharygolba authored Aug 7, 2016
1 parent 48d2fb7 commit 5de7a0d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 34 deletions.
11 changes: 5 additions & 6 deletions src/packages/database/query/utils/build-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,17 @@ export default async function buildResults<T: Model>({

if (relationship) {
let { foreignKey } = relationship;

foreignKey = camelize(foreignKey, true);

const match = relatedResults.filter(({ rawColumnData }) => {
Reflect.set(record, name, relatedResults.filter(({
rawColumnData
}) => {
const fk = Reflect.get(rawColumnData, foreignKey);
const pk = Reflect.get(record, model.primaryKey);

return fk === pk;
});

if (match.length) {
Reflect.set(record, name, match);
}
}));
}
});
}
Expand Down
28 changes: 8 additions & 20 deletions src/packages/database/relationship/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function get(
}

const related = relatedFor(owner);
const { type, model, inverse } = opts;
const { type } = opts;
let { foreignKey } = opts;
let value = related.get(key);

Expand All @@ -31,27 +31,21 @@ export async function get(
switch (type) {
case 'hasOne':
value = await getHasOne(owner, {
type,
model,
inverse,
...opts,
foreignKey
});
break;

case 'hasMany':
value = await getHasMany(owner, {
type,
model,
inverse,
...opts,
foreignKey
});
break;

case 'belongsTo':
value = await getBelongsTo(owner, {
type,
model,
inverse,
...opts,
foreignKey
});
break;
Expand All @@ -70,32 +64,26 @@ export function set(owner: Model, key: string, value?: Array<Model> | ?Model) {
const opts = owner.constructor.relationshipFor(key);

if (opts) {
const { type, model, inverse } = opts;
const { type } = opts;
let { foreignKey } = opts;

foreignKey = camelize(foreignKey, true);

if (Array.isArray(value)) {
if (type === 'hasMany') {
setHasMany(owner, key, value, {
type,
model,
inverse,
...opts,
foreignKey
});
}
} else if (type === 'hasOne') {
setHasOne(owner, key, value, {
type,
model,
inverse,
...opts,
foreignKey
});
} else if (type === 'belongsTo') {
setBelongsTo(owner, key, value, {
type,
model,
inverse,
...opts,
foreignKey
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/packages/database/relationship/interfaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ export type Relationship$opts = {
type: 'hasOne' | 'hasMany' | 'belongsTo';
model: Class<Model>;
inverse: string;
through?: string;
through?: Class<Model>;
foreignKey: string;
};
49 changes: 42 additions & 7 deletions src/packages/database/relationship/utils/getters.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
// @flow
import { camelize } from 'inflection';

import type { Model } from '../../index';
import type { Relationship$opts } from '../index';

/**
* @private
*/
async function getHasManyThrough(owner: Model, {
model,
inverse,
through,
foreignKey: baseKey
}: Relationship$opts) {
const inverseOpts = model.relationshipFor(inverse);

if (through && inverseOpts) {
let { foreignKey } = inverseOpts;

foreignKey = camelize(foreignKey, true);

const records = await through.select(baseKey, foreignKey).where({
[baseKey]: owner.getPrimaryKey()
});

if (!records.length) {
return [];
}

return await model.where({
[model.primaryKey]: records
.map(record => Reflect.get(record, foreignKey))
.filter(Boolean)
});
} else {
return [];
}
}

/**
* @private
*/
Expand All @@ -10,19 +46,18 @@ export function getHasOne(owner: Model, {
foreignKey
}: Relationship$opts) {
return model.first().where({
[foreignKey]: Reflect.get(owner, owner.constructor.primaryKey)
[foreignKey]: owner.getPrimaryKey()
});
}

/**
* @private
*/
export function getHasMany(owner: Model, {
model,
foreignKey
}: Relationship$opts) {
return model.where({
[foreignKey]: Reflect.get(owner, owner.constructor.primaryKey)
export function getHasMany(owner: Model, opts: Relationship$opts) {
const { model, through, foreignKey } = opts;

return through ? getHasManyThrough(owner, opts) : model.where({
[foreignKey]: owner.getPrimaryKey()
});
}

Expand Down

0 comments on commit 5de7a0d

Please sign in to comment.