Merge pull request #257 from bhunjadi/reducers

Reducers
This commit is contained in:
Theodor Diaconu 2018-06-07 00:43:48 +03:00 committed by GitHub
commit 824047824d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 13 deletions

0
lib/namedQuery/namedQuery.base.js Normal file → Executable file
View file

65
lib/query/lib/prepareForDelivery.js Normal file → Executable file
View file

@ -9,9 +9,10 @@ import {Minimongo} from 'meteor/minimongo';
export default (node, params) => {
snapBackCaches(node);
storeOneResults(node, node.results);
applyReducers(node, params);
cleanReducerLeftovers(node);
_.each(node.collectionNodes, collectionNode => {
cloneMetaChildren(collectionNode, node.results)
});
@ -21,7 +22,6 @@ export default (node, params) => {
});
removeLinkStorages(node, node.results);
storeOneResults(node, node.results);
applyPostFilters(node);
applyPostOptions(node);
applyPostFilter(node, params);
@ -67,11 +67,31 @@ function applyPostFilter(node, params) {
}
}
/**
*
* Helper function which transforms results into the array.
* Results are an object for 'one' links.
*
* @param results
* @return array
*/
export function getResultsArray(results) {
if (_.isArray(results)) {
return results;
}
else if (_.isUndefined(results)) {
return [];
}
return [results];
}
export function removeLinkStorages(node, sameLevelResults) {
if (!sameLevelResults) {
return;
}
sameLevelResults = getResultsArray(sameLevelResults);
_.each(node.collectionNodes, collectionNode => {
const removeStorageField = collectionNode.shouldCleanStorage;
_.each(sameLevelResults, result => {
@ -114,11 +134,19 @@ function cloneMetaChildren(node, parentResults) {
const linkName = node.linkName;
const isMeta = node.isMeta;
// parentResults might be an object (for type==one links)
parentResults = getResultsArray(parentResults);
parentResults.forEach(parentResult => {
if (isMeta && parentResult[linkName]) {
parentResult[linkName] = parentResult[linkName].map(object => {
return Object.assign({}, object);
});
if (node.isOneResult) {
parentResult[linkName] = Object.assign({}, parentResult[linkName]);
}
else {
parentResult[linkName] = parentResult[linkName].map(object => {
return Object.assign({}, object);
});
}
}
node.collectionNodes.forEach(collectionNode => {
@ -128,6 +156,8 @@ function cloneMetaChildren(node, parentResults) {
}
export function assembleMetadata(node, parentResults) {
parentResults = getResultsArray(parentResults);
// assembling metadata is depth first
node.collectionNodes.forEach(collectionNode => {
_.each(parentResults, result => {
@ -140,20 +170,31 @@ export function assembleMetadata(node, parentResults) {
_.each(parentResults, parentResult => {
const childResult = parentResult[node.linkName];
_.each(childResult, object => {
const storage = object[node.linkStorageField];
if (node.isOneResult) {
const storage = childResult[node.linkStorageField];
storeMetadata(childResult, parentResult, storage, true);
} else {
_.each(childResult, object => {
const storage = object[node.linkStorageField];
storeMetadata(object, parentResult, storage, true);
});
storeMetadata(object, parentResult, storage, true);
});
}
})
} else {
_.each(parentResults, parentResult => {
const childResult = parentResult[node.linkName];
const storage = parentResult[node.linkStorageField];
_.each(childResult, object => {
storeMetadata(object, parentResult, storage, false);
});
if (node.isOneResult) {
if (childResult) {
storeMetadata(childResult, parentResult, storage, false);
}
} else {
_.each(childResult, object => {
storeMetadata(object, parentResult, storage, false);
});
}
})
}
}

15
lib/query/testing/bootstrap/comments/links.js Normal file → Executable file
View file

@ -16,4 +16,17 @@ Comments.addLinks({
field: 'postId',
index: true
}
});
});
Comments.addReducers({
authorLinkReducer: {
body: {
author: {
name: 1,
},
},
reduce(object) {
return object.author;
}
}
});

18
lib/query/testing/reducers.server.test.js Normal file → Executable file
View file

@ -1,4 +1,6 @@
import { createQuery } from 'meteor/cultofcoders:grapher';
import Authors from './bootstrap/authors/collection';
import Comments from './bootstrap/comments/collection';
describe('Reducers', function () {
it('Should work with field only reducers', function () {
@ -71,6 +73,22 @@ describe('Reducers', function () {
})
});
it('Should work with One link reducers', function () {
const sampleComment = Comments.findOne();
const comment = createQuery({
comments: {
$filters: {
_id: sampleComment._id,
},
authorLinkReducer: 1,
}
}).fetchOne();
assert.isObject(comment);
assert.isObject(comment.authorLinkReducer);
});
it('Should work with links and nested reducers', function () {
const data = createQuery({
authors: {

23
lib/query/testing/server.test.js Normal file → Executable file
View file

@ -170,6 +170,29 @@ describe('Hypernova', function() {
});
});
it('Should fetch Many-Meta links correctly where parent is One link', function () {
const data = createQuery({
posts: {
$options: { limit: 5 },
author: {
groups: {
isAdmin: 1
}
}
}
}).fetch();
_.each(data, post => {
assert.isObject(post.author);
assert.isArray(post.author.groups);
_.each(post.author.groups, group => {
assert.isObject(group.$metadata);
assert.isBoolean(group.$metadata.isAdmin);
});
});
});
it('Should fetch Many-Meta inversed links correctly', function() {
const data = createQuery({
groups: {