Skip to content

Commit

Permalink
Merge branch 'release-3.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoboucas committed Jun 13, 2018
2 parents b1c9b2c + c6fdb09 commit c7e9e5e
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 26 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [3.2.1] (2018-06-13)

### Changed

* [#435](https://github.com/dadi/api/issues/435): Fix issue where filtering `Object` fields with nested queries would return a 400 error.

## [3.2.0] (2018-06-08)

See release notes at https://github.com/dadi/api/releases/tag/v3.2.0
Expand Down
56 changes: 46 additions & 10 deletions dadi/lib/fields/reference.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const objectPath = require('object-path')
const path = require('path')

module.exports.type = 'reference'
Expand All @@ -13,9 +12,6 @@ module.exports.type = 'reference'
*/
function createModelChain (rootModel, fields) {
return fields.reduce((chain, field, index) => {
// Propagating an error state.
if (chain === null) return chain

if (chain.length === 0) {
return chain.concat(rootModel)
}
Expand All @@ -31,7 +27,7 @@ function createModelChain (rootModel, fields) {
!referenceField.type.length ||
referenceField.type.toLowerCase() !== 'reference'
) {
return null
return chain.concat(null)
}

let referenceCollection = field.split('@')[1] ||
Expand Down Expand Up @@ -259,11 +255,51 @@ module.exports.beforeQuery = function ({config, field, input, options}) {
// }
// }
// }
let inputTree = Object.keys(input).reduce((tree, path) => {
objectPath.set(tree, path, input[path])
//
// It looks at the various models in the chain to look for fields
// that are not Reference fields. When it finds one, it leaves the
// dot-notation in the node key, rather than expanding it out. For
// example, imagine that `status` is a field of type Object:
//
// In:
// {
// "book.author.occupation": "writer",
// "book.status.live": true
// }
//
// Out:
// {
// "book": {
// "author": {
// "occupation": "writer"
// },
// "status.live": true
// }
// }
let inputTree = {}

return tree
}, {})
Object.keys(input).forEach(path => {
let nodes = path.split('.')
let modelChain = createModelChain(this, nodes)
let pointer = inputTree

let interrupted = nodes.slice(0, -1).some((node, index) => {
if (!modelChain[index + 1]) {
let key = nodes.slice(index).join('.')

pointer[key] = input[path]

return true
}

pointer[node] = Object.assign({}, pointer[node])
pointer = pointer[node]
})

if (!interrupted) {
pointer[nodes.slice(-1)] = input[path]
}
})

// This function takes a tree like the one in the example above and
// processes it recursively, running the `find` method in the
Expand Down Expand Up @@ -298,7 +334,7 @@ module.exports.beforeQuery = function ({config, field, input, options}) {

let firstKey = Object.keys(tree)[0]
let modelChain = createModelChain(this, path.concat(firstKey))
let model = modelChain[modelChain.length - 1]
let model = modelChain && modelChain[modelChain.length - 1]

return queue.then(query => {
if (path.length === 0) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dadi/api",
"version": "3.2.0",
"version": "3.2.1",
"main": "main.js",
"scripts": {
"create-client": "cd ../../.. && node ./node_modules/@dadi/api/utils/create-client.js",
Expand Down
84 changes: 69 additions & 15 deletions test/acceptance/fields/reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('Reference Field', () => {
.set('Authorization', 'Bearer ' + bearerToken)
.send(book)
.expect(200)
.end((err, res) => {
.end((err, res) => {
res.body.results[0].author.name.should.eql(author.name)

done()
Expand Down Expand Up @@ -101,7 +101,7 @@ describe('Reference Field', () => {
.set('Authorization', 'Bearer ' + bearerToken)
.send(book)
.expect(200)
.end((err, res) => {
.end((err, res) => {
res.body.results[0].author.length.should.eql(3)
res.body.results[0].author[0].name.should.eql(authors[0].name)
res.body.results[0].author[1].name.should.eql(authors[1].name)
Expand Down Expand Up @@ -197,7 +197,7 @@ describe('Reference Field', () => {
doc._refMultiReference[bookIds[1]].should.eql('book')

done()
})
})
})
})
})
Expand Down Expand Up @@ -341,10 +341,10 @@ describe('Reference Field', () => {
res.body.results[0].book.author.name.should.eql(event.book.author.name)

done()
})
})
})
})
})
})

it('should create reference documents recursively in the collections specified by the `_collection` field', done => {
let item = {
Expand Down Expand Up @@ -434,7 +434,7 @@ describe('Reference Field', () => {

done()
})
})
})
})
})
})
Expand Down Expand Up @@ -639,7 +639,7 @@ describe('Reference Field', () => {

newDoc.author._id.should.eql(authorId)
newDoc.author.name.should.eql('Ernest Hemingway')

client
.get('/v1/library/person/' + authorId)
.set('Authorization', 'Bearer ' + bearerToken)
Expand All @@ -652,7 +652,7 @@ describe('Reference Field', () => {
res.body.results[0].name.should.eql('Ernest Hemingway')

done()
})
})
})
})
})
Expand Down Expand Up @@ -1059,9 +1059,9 @@ describe('Reference Field', () => {

done()
})
})
})
})
})
})
})
})

Expand Down Expand Up @@ -1372,7 +1372,61 @@ describe('Reference Field', () => {

done()
})
})
})
})
})

it('should filter documents by nested objects properties', done => {
let event = {
type: 'Book status',
book: {
title: 'For Whom The Bell Tolls',
publishStatus: {
status: 'published',
rights: 'public domain'
},
author: {
name: 'Ernest Hemingway'
}
}
}

config.set('query.useVersionFilter', true)

let client = request(connectionString)
client
.post('/v1/library/event')
.set('Authorization', 'Bearer ' + bearerToken)
.send(event)
.expect(200)
.end((err, res) => {
if (err) return done(err)

client
.get('/v1/library/event?filter={"book.publishStatus.status":"draft"}')
.set('Authorization', 'Bearer ' + bearerToken)
.expect(200)
.end((err, res) => {
if (err) return done(err)

res.body.results.length.should.eql(0)

client
.get('/v1/library/event?filter={"book.publishStatus.status":"published"}&compose=true')
.set('Authorization', 'Bearer ' + bearerToken)
.expect(200)
.end((err, res) => {
if (err) return done(err)

res.body.results.length.should.eql(1)
res.body.results[0].type.should.eql(event.type)

should.exist(res.body.results[0].book.publishStatus)
res.body.results[0].book.publishStatus.status.should.eql('published')

done()
})
})
})
})

Expand Down Expand Up @@ -1401,7 +1455,7 @@ describe('Reference Field', () => {
config.set('query.useVersionFilter', true)

let client = request(connectionString)

client
.post('/v1/library/misc')
.set('Authorization', 'Bearer ' + bearerToken)
Expand Down Expand Up @@ -1568,7 +1622,7 @@ describe('Reference Field', () => {
name: 'Ernest Hemingway',
spouse: {
name: 'Mary Welsh Hemingway'
}
}
}
},
{
Expand All @@ -1577,7 +1631,7 @@ describe('Reference Field', () => {
title: 'War and Peace',
author: {
name: 'Leo Tolstoy'
}
}
}
}
]
Expand Down Expand Up @@ -1756,7 +1810,7 @@ describe('Reference Field', () => {
done()
})
})
})
})

describe('when `settings.strictCompose` is not enabled', () => {
it('should return unique results for a reference field containing an Array of Strings', done => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"collection": "person"
}
},
"publishStatus": {
"type": "Object"
},
"authorStrict": {
"type": "Reference",
"settings": {
Expand Down

0 comments on commit c7e9e5e

Please sign in to comment.