Kay Kay - 1 month ago 12
Node.js Question

Nodejs and Express - Nested routers not hitting controller function

A user has a profile object and a profile has an array of interests

let UserSchema = new Schema({

email: {
value: {
type: String,
lowercase: true,
//unique: true,

},
token: String,
verified: Boolean,
},
password: {
type: String,
},

phone: {
countryCode: {
type: String,
//required:true,
unique: true,
},
number: {
type: String,
required: true
},
code: String,
verified: {
type: Boolean,
default: false
},
},

jwt: String,

profile: {
username: String,
firstname: String,
lastname: String,
dob: String,
level: Number,
location: String,
image: String,
introduction: String,

languages: {
teach: [{
code: String,
name: String,
native: String,
level: Number,
}],
learn: [{
code: String,
name: String,
native: String,
level: Number,
}],
},
interests: [],
countries: [],
},
},
{
timestamps: {createdAt: 'created_at', updatedAt: 'updated_at'}
});


I have a scenario where i just want to add interests to a users profile. The request would be something like this to show all the users interest.

GET: /users/:id/profile/interest

user.router.js

'use strict';

let express = require('express');
let router = express.Router();
let controller = require('../controllers/user.controller');
controller = new controller();

router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.store);
router.put('/:id', controller.update);
router.delete('/:id', controller.destroy);

router.use('/:id/profile', require('./profile.route'));

module.exports = router;


profile.router.js

let express = require('express');
let router = express.Router({mergeParams: true});
let controller = require('../controllers/profile.controller');
controller = new controller();

router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.store);
router.put('/:id', controller.update);
router.delete('/:id', controller.destroy);

router.use('/interest', require('./interest.route'));

module.exports = router;


interest.router.js

'use strict';

let express = require('express');
let router = express.Router({mergeParams: true});
let controller = require('../controllers/interest.controller');
controller = new controller();

router.post('/', controller.store);
router.get('/', controller.show);

module.exports = router;


interest.controller.js

show(req, res) {
let id = req.params.id;
console.log(id);

User.findOne({'_id': id}, function (err, user) {

if (err) return res.json(err);

return res.json(user);

});
}


When i call this GET: /users/:id/profile/interest request, it should hit the show function in the interest controller. However, it is not doing so. Postman gives me an error of.

{
"message": "Cast to ObjectId failed for value \"interest\" at path \"_id\" for model \"User\"",
"name": "CastError",
"stringValue": "\"interest\"",
"kind": "ObjectId",
"value": "interest",
"path": "_id"
}


How do i solve this?

P.S If you can think of a more efficient way to do this process please this let me know.

Answer Source

I think your route is being matched earlier than you want, try moving your router.use line up a bit in your profile.router.js code:

let express    = require('express');
let router     = express.Router({mergeParams: true});
let controller = require('../controllers/profile.controller');
controller     = new controller();

router.use('/interest', require('./interest.route')); 

router.get('/', controller.index);
router.get('/:id', controller.show); /* the /interest route was being matched here */
router.post('/', controller.store);
router.put('/:id', controller.update);
router.delete('/:id', controller.destroy);

module.exports = router;

`