Merge pull request #1306 from strongloop/feature/allow-filter-on-findById

Expose the `filter` argument for findById
This commit is contained in:
Raymond Feng 2015-04-16 15:12:50 -07:00
commit 3dcde7994b
3 changed files with 87 additions and 12 deletions

View File

@ -142,15 +142,20 @@ module.exports = function(registry) {
};
/**
* Find object by ID.
* Find object by ID with an optional filter for include/fields.
*
* @param {*} id Primary key value
* @options {Object} [filter] Optional Filter JSON object; see below.
* @property {String|Object|Array} fields Identify fields to include in return result.
* <br/>See [Fields filter](http://docs.strongloop.com/display/LB/Fields+filter).
* @property {String|Object|Array} include See PersistedModel.include documentation.
* <br/>See [Include filter](http://docs.strongloop.com/display/LB/Include+filter).
* @callback {Function} callback Callback function called with `(err, instance)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://docs.strongloop.com/display/LB/Error+object).
* @param {Object} instance Model instance matching the specified ID or null if no instance matches.
*/
PersistedModel.findById = function find(id, cb) {
PersistedModel.findById = function find(id, filter, cb) {
throwNotAttached(this.modelName, 'findById');
};
@ -180,7 +185,7 @@ module.exports = function(registry) {
* @param {Array} models Model instances matching the filter, or null if none found.
*/
PersistedModel.find = function find(params, cb) {
PersistedModel.find = function find(filter, cb) {
throwNotAttached(this.modelName, 'find');
};
@ -209,7 +214,7 @@ module.exports = function(registry) {
* @param {Array} model First model instance that matches the filter or null if none found.
*/
PersistedModel.findOne = function findOne(params, cb) {
PersistedModel.findOne = function findOne(filter, cb) {
throwNotAttached(this.modelName, 'findOne');
};
@ -573,10 +578,12 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'findById', {
description: 'Find a model instance by id from the data source.',
accessType: 'READ',
accepts: {
arg: 'id', type: 'any', description: 'Model id', required: true,
http: {source: 'path'}
},
accepts: [
{ arg: 'id', type: 'any', description: 'Model id', required: true,
http: {source: 'path'}},
{ arg: 'filter', type: 'object',
description: 'Filter defining fields and include'}
],
returns: {arg: 'data', type: typeName, root: true},
http: {verb: 'get', path: '/:id'},
rest: {after: convertNullToNotFoundError}
@ -585,7 +592,7 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'find', {
description: 'Find all instances of the model matched by filter from the data source.',
accessType: 'READ',
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, order, offset, and limit'},
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
returns: {arg: 'data', type: [typeName], root: true},
http: {verb: 'get', path: '/'}
});
@ -593,7 +600,7 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'findOne', {
description: 'Find first instance of the model matched by filter from the data source.',
accessType: 'READ',
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, order, offset, and limit'},
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
returns: {arg: 'data', type: typeName, root: true},
http: {verb: 'get', path: '/findOne'},
rest: {after: convertNullToNotFoundError}

View File

@ -66,7 +66,7 @@ describe('Model / PersistedModel', function() {
describe.onServer('Remote Methods', function() {
var User;
var User, Post;
var dataSource;
var app;
@ -84,11 +84,22 @@ describe.onServer('Remote Methods', function() {
trackChanges: true
});
Post = PersistedModel.extend('post', {
id: { id: true, type: String, defaultFn: 'guid' },
title: String,
content: String
}, {
trackChanges: true
});
dataSource = loopback.createDataSource({
connector: loopback.Memory
});
User.attachTo(dataSource);
Post.attachTo(dataSource);
User.hasMany(Post);
User.login = function(username, password, fn) {
if (username === 'foo' && password === 'bar') {
@ -163,6 +174,63 @@ describe.onServer('Remote Methods', function() {
done();
});
});
it('Call the findById with filter.fields using HTTP / REST', function(done) {
request(app)
.post('/users')
.send({first: 'x', last: 'y'})
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
var userId = res.body.id;
assert(userId);
request(app)
.get('/users/' + userId + '?filter[fields]=first')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
assert.equal(res.body.first, 'x', 'first should be x');
assert(res.body.last === undefined, 'last should not be present');
done();
});
});
});
it('Call the findById with filter.include using HTTP / REST', function(done) {
request(app)
.post('/users')
.send({first: 'x', last: 'y'})
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
var userId = res.body.id;
assert(userId);
request(app)
.post('/users/' + userId + '/posts')
.send({title: 'T1', content: 'C1'})
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
var post = res.body;
request(app)
.get('/users/' + userId + '?filter[include]=posts')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
assert.equal(res.body.first, 'x', 'first should be x');
assert.equal(res.body.last, 'y', 'last should be y');
assert.deepEqual(post, res.body.posts[0]);
done();
});
});
});
});
});
describe('Model.beforeRemote(name, fn)', function() {

View File

@ -114,7 +114,7 @@ describe('remoting - integration', function() {
'create(data:object):store POST /stores',
'upsert(data:object):store PUT /stores',
'exists(id:any):boolean GET /stores/:id/exists',
'findById(id:any):store GET /stores/:id',
'findById(id:any,filter:object):store GET /stores/:id',
'find(filter:object):store GET /stores',
'findOne(filter:object):store GET /stores/findOne',
'updateAll(where:object,data:object) POST /stores/update',