Skip to content

Commit

Permalink
WEB-1962 top-level resource filters
Browse files Browse the repository at this point in the history
  • Loading branch information
jesuscript committed Mar 21, 2014
1 parent 71cc6da commit d3cea1c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 50 deletions.
71 changes: 30 additions & 41 deletions lib/adapters/nedb.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
var fs = require('fs')
, path = require('path')
, mkdirp = require('mkdirp')
, NeDB = require('nedb')
, RSVP = require('rsvp')
, _ = require('lodash')
, location = path.normalize(__dirname);
, path = require('path')
, mkdirp = require('mkdirp')
, NeDB = require('nedb')
, RSVP = require('rsvp')
, _ = require('lodash')
, location = path.normalize(__dirname);

var adapter = {};

Expand All @@ -16,11 +16,11 @@ adapter._init = function(options) {
adapter.schema = function(name, schema, options) {
_.each(schema, function(val, key) {
var obj = {}
, isArray = _.isArray(val)
, value = isArray ? val[0] : val
, isObject = _.isPlainObject(value)
, ref = isObject ? value.ref : value
, inverse = isObject ? value.inverse : undefined;
, isArray = _.isArray(val)
, value = isArray ? val[0] : val
, isObject = _.isPlainObject(value)
, ref = isObject ? value.ref : value
, inverse = isObject ? value.inverse : undefined;

// Convert string to association object
if(typeof ref === 'string') {
Expand All @@ -42,8 +42,8 @@ adapter.schema = function(name, schema, options) {
adapter.model = function(name, schema) {
if(schema) {
var dbPath = this._options.path + this._options.db
, filePath = dbPath + '/' + this.inflect.pluralize(name)
, options = {
, filePath = dbPath + '/' + this.inflect.pluralize(name)
, options = {
filename: filePath,
autoload: true
};
Expand All @@ -53,7 +53,7 @@ adapter.model = function(name, schema) {
mkdirp.sync(dbPath);
fs.exists(filePath, function(exists) {
if(!exists) {
fs.writeFileSync(filePath, '');
fs.writeFileSync(filePath, '');
}
});
}
Expand Down Expand Up @@ -126,14 +126,8 @@ adapter.find = function(model, query) {
var _this = this,
fields = [];

if(typeof query === 'object'){
fields = query.fields || [];
query = {_id: query.id};
}else{
query = {_id: query};
model = typeof model === 'string' ? this._models[model] : model;
}

if(!_.isObject(query)) query = {_id: query};

return new RSVP.Promise(function(resolve, reject) {
model.findOne(query, function(error, resource) {
if(error || !resource) return reject(error);
Expand All @@ -143,26 +137,21 @@ adapter.find = function(model, query) {
};

adapter.findMany = function(model, query, limit) {
var _this = this,
dbQuery = {};

if(_.isArray(query) && query.length) {
dbQuery = {_id: {$in: query}};
} else if(_.isNumber(query)) {
limit = query;
} else if(_.isObject(query)) {
dbQuery = (query._id && query._id.length) ? {_id: {$in: query._id}} : {};
}
var _this = this;

model = typeof model === 'string' ? this._models[model] : model;
limit = limit || 1000; //doesn't look like this is used anywhere

if(_.isArray(query)) query = {_id: {$in: query}};
if(_.isNumber(query) || _.isString(query)) query = {_id: query};

return new RSVP.Promise(function(resolve, reject) {
model.find(dbQuery, function(error, resources) {
model.find(query, function(error, resources) {
if(error) return reject(error);
resources = resources.map(function(resource) {
return _this._deserialize(model, resource);
});
resolve(resources);
return resolve(resources);
}); //how about .limit(limit)?
});
};
Expand Down Expand Up @@ -253,12 +242,12 @@ adapter._project = function(json, fields){
*/
adapter._scrubResource = function(model, resource) {
var json = {}
, schema = this._schemas[model._name];
, schema = this._schemas[model._name];

_.each(schema, function(value, key) {
var type = value.type
, typeString = type ? typeCheck(type) : ''
, ref = _.isArray(value) ? value[0].ref : value.ref;
, typeString = type ? typeCheck(type) : ''
, ref = _.isArray(value) ? value[0].ref : value.ref;

if(!resource.hasOwnProperty(key)) return;

Expand Down Expand Up @@ -319,7 +308,7 @@ adapter._updateRelationships = function(model, resource) {
var references = [];
_.each(this._schemas[model._name], function(value, key) {
var singular = !_.isArray(value)
, obj = singular ? value : value[0];
, obj = singular ? value : value[0];

if(typeof obj === 'object' && obj.hasOwnProperty('ref')) {
references.push({
Expand All @@ -334,8 +323,8 @@ adapter._updateRelationships = function(model, resource) {
var promises = [];
_.each(references, function(reference) {
var relatedModel = _this._models[reference.model]
, relatedSchema = _this._schemas[reference.model]
, fields = [];
, relatedSchema = _this._schemas[reference.model]
, fields = [];

// Get fields on the related model that reference this model
if(typeof reference.inverse === 'string') {
Expand All @@ -347,7 +336,7 @@ adapter._updateRelationships = function(model, resource) {
}
_.each(relatedSchema, function(value, key) {
var singular = !_.isArray(value)
, obj = singular ? value : value[0];
, obj = singular ? value : value[0];
if(typeof obj === 'object' && obj.ref === model._name) {
fields.push({
path: key,
Expand Down
24 changes: 17 additions & 7 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,16 @@ function route(name, model, inflect) {
var ids = [];
var fields = req.query.fields ? req.query.fields.split(",") : [];

if(typeof req.query.ids === 'string') ids = req.query.ids.split(',');
if(typeof req.query.ids === 'array') ids = req.query.ids;
if(req.query.ids) match._id = {$in: req.query.ids.split(',')};

//only pick top-level filters
var filters = _.reduce(req.query.filter, function(memo, v, k){
if(_.isString(v)) memo[k] = v;
return memo;
},{});

if(ids.length) match._id = {$in: ids};
// get resources by IDs
adapter.findMany(model, match)
adapter.findMany(model, _.extend(match,filters))

// do after transforms
.then(function(resources) {
Expand Down Expand Up @@ -234,11 +238,14 @@ function route(name, model, inflect) {
* Get an individual resource, or many.
*/
router.get(individualRoute, function(req, res) {
var match = {};
var ids = req.params.id.split(',');
var fields = req.query.fields ? req.query.fields.split(",") : [];

if(ids) match._id = {$in: ids};

// get resources by IDs
adapter.findMany(model, ids)
adapter.findMany(model, match)

// do after transforms
.then(function(resources) {
Expand Down Expand Up @@ -270,10 +277,13 @@ function route(name, model, inflect) {
router.get(individualRoute + '/:key' + suffix, function(req, res) {
var id = req.params.id,
key = req.params.key,
fields = req.query.fields ? req.query.fields.split(",") : [];
fields = req.query.fields ? req.query.fields.split(",") : [],
match = {};

if(id) match._id = id;

// get a resource by ID
adapter.find(model, id)
adapter.find(model, match)

// do after transform
.then(function(resource) {
Expand Down
18 changes: 16 additions & 2 deletions test/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ _.each(global.adapters, function(port, adapter) {
_.each(fixtures, function(resources, collection) {
createResources.push(new RSVP.Promise(function(resolve, reject) {
var body = {};
body[collection] = resources;
body[collection] = resources;
request(baseUrl)
.post('/' + collection)
.send(body)
.expect('Content-Type', /json/)
.expect(201)
.end(function(error, response) {
.end(function(error, response) {
if(error) return reject(error);
var resources = JSON.parse(response.text)[collection];
ids[collection] = ids[collection] || [];
Expand Down Expand Up @@ -358,6 +358,20 @@ _.each(global.adapters, function(port, adapter) {
});
});

describe("filters", function(){
it("should allow top-level resource filtering for collection routes", function(done){
request(baseUrl).get('/people?filter[name]=Robert')
.expect('Content-Type', /json/)
.expect(200)
.end(function(error, response){
should.not.exist(error);
var body = JSON.parse(response.text);
body.people.length.should.equal(1);
done();
});
});
});


describe('compound document support', function() {
it("for a person should return pets, soulmate and lovers links", function(done) {
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
{
"name": "Wally",
"appearances": 1934
},
{
"name": "Robert",
"appearances": 0
}
],
"pets": [
Expand Down
1 change: 1 addition & 0 deletions test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var Mocha = require('mocha')
if(!process.env.TRAVIS) {
var config = {};
config[process.argv[2] || 'nedb'] = 8890;
config.mongodb = 8891;
runTests(config);
} else {
runTests({
Expand Down

0 comments on commit d3cea1c

Please sign in to comment.