How to do it...

Let's follow these steps to learn how to populate our user's blog post list with their blog post content:

  1. First, we will need to restructure our /middleware/rest.js middleware to allow a full set of override methods, not just the middleware callback. We will do that using the lodash default to allow us to merge our custom methods with the rest of the default REST API callbacks defined below it:
...
var _defaults = require('lodash/defaults');

module.exports = function(resourceId, store, serialize, deserialize, overrides) {
...
return resource(_defaults(overrides, {
...
}));
};
  1. To make sure we don't break our /routes/api/posts.js route configuration, we should update restFactory to use this new override option for our middleware hook:
...

module.exports = restFactory('posts', Posts, serialize, deserialize, {

middleware: function(req, res, next) {
req.query = _pick(req.query, ['_size', '_page', '_search', 'title', 'published']);
if (req.query.published) {

try {
req.query.published = JSON.parse(req.query.published);
} catch(error) {

console.error('unable to parse published date format');
}

}
next();
}

});
  1. Next, in our /routes/api/users.js route configuration, we will override the load and read options of our restFactory REST API callbacks, so that we can target specific fields in a user record for population. To do this, we will create a new custom serializer that will recognize the attributes for the nested post model properties and properly serialize them in our JSON API response:
var express = require('express');
var router = express.Router();
var restFactory = require('../../middleware/rest');
var Users = require('../../models/users');
var JSONAPISerializer = require('jsonapi-serializer').Serializer;
var _clone = require('lodash/clone')
;

var serialize = {
transform: function(user) {
return user.toObject();
},
id: '_id',
attributes: ['firstName', 'lastName', 'email', 'role', 'posts'],
posts: {
ref: true
}
};

var deserialize = {
keyForAttribute: 'dash-case'
};

var populatedSerialize = _clone(serialize);
populatedSerialize.posts = {

ref: '_id',
attributes: ['title', 'content', 'html', 'published']

};
var populatedSerializer = new JSONAPISerializer('users', populatedSerialize);

module.exports = restFactory('users', Users, serialize, deserialize, {
load: function(req, id, callback) {
var query = Users.findById(id);
query.populate('posts');
query.exec(function(error, item) {

callback(null, item);
});
},

read: function(req, res) {

res.json(populatedSerializer.serialize(req['users']));
}

});
  1. Because we are overriding the default method for handling finding and loading an individual user record, we will also need to add our own error handling here:
...
var JSONAPIError = require('jsonapi-serializer').Error;
...
module.exports = restFactory('users', Users, serialize, deserialize, {
load: function(req, id, callback) {
var query = Users.findById(id);
query.populate('posts');
query.exec(function(error, item) {
if (error) return callback(new JSONAPIError({
status: 400,
title: error.name || 'Database Request Failed',
detail: error.message || 'Unable to handle requested database operation.'
}));

if (!item) return callback(new JSONAPIError({

status: 404,
title: 'Not found',
detail: 'Resource ' + id + ' does not exist.'
}));

callback(null, item);
});
},
...
});
  1. Now when we make requests for individual users, we can see that the included property contains posts that have all their details, including their virtual properties, serialized into it:
...
"included"
: [
{
"type": "posts",
"id": "596ac2d78624af295aa08d81",
"attributes": {
"title": "dolores qui eum",
"content": "Aut voluptas velit quis incidunt...",
"html": "<p>Aut voluptas velit quis incidunt..."
"published": "2016-11-07T03:28:58.649Z"
}
},
...
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.181.66