Beginning Node.js – REST API with a Mongodb backend (refactoring) – part 4

Refactoring

This code in the entry point main.js in the former post is a bit verbose. If an application becomes more complex you don't really want to put all your logic in one file. Best practice is to keep thing small, by making every program a proxy.

Disclaimer: my blog posts may not be best practice for everybody in every situation. The code I share however works for me and gets the job done. I strive to keep everything as simple as possibe.

Model, View, Controller

In this post we will create a Model and a Controller (no Views because this is still just a REST API without a frontend).
Finally we'll create the routes.

The main.js file requires the routes, the routes require the controller, the controller requires the model.

Yep, that should do.

Create a model

So let's clean out the mess. Create a new folder named 'app'. From the main.js file we will put the 'Food' model into a separate file.

I will save the file as model.food.js.

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var FoodSchema = new Schema({
    name: String,
    description: String,
    price: String
});

mongoose.model('Food', FoodSchema);
module.exports = mongoose.model('Food');

'Module.exports' wraps everything so that later on you can "require" this module and use the "new" operator to create a new instance of the Food object type, which is done in the controller in the next paragraph.

Create a controller

I put the CRUD into a controller (per this example).
I will save the file as controller.food.js
Notice how I 'require' the Model in the first line.

var Food = require('./model.food.js');

exports.create = function (req, res) {
    var food = new Food(req.body);
    console.log(food);
    food.save(function (err) {
        if (err) {
            return res.send({
                message: err
            });
        } else {
            res.send({
                success: true,
                food: food
            });
        }
    });
};

exports.list = function (req, res) {
    Food.find(function (err, data) {
        if (err) {
            res.send(err);
        }
        res.json({
            success: true,
            food: data
        });
    });
};


exports.findOne = function (req, res) {
    Food.findOne({
        _id: req.params.id
    }, function (error, response) {
        if (error) {
            res.send(error);
        } else {
            res.send({
                success: true,
                food: response
            });
        }
    });
};

exports.findByName = function (req, res) {
    Food.findOne({
        name: req.params.name
    }, function (error, response) {
        if (error || !response) {
            res.status(404).send({
                status: 401,
                message: 'not found'
            });
        } else {
            res.send({
                success: true,
                food: response
            });
        }
    });
}

Here I am basically wrapping methods around the Food object, using exports.methodname.
In case you are wondering (I was, and have to admit still am wondering about this sometimes), this article explains the difference between 'module.exports' and 'exports' as follows: 'module.exports' is the real deal, exports is just its little helper. For now, I am OK with that. Let's just get things done already. πŸ™‚

Separate the routes

Here the controller.food.js file is required.
I will save the file as routes.food.js.

//mongodb
var foodstuff = require('./controller.food');

module.exports = function (app) {
    app.route('/food').post(foodstuff.create);
    app.route('/food').get(foodstuff.list);
    app.route('/food/:id').get(foodstuff.findOne);
    app.route('/foodname/:name').get(foodstuff.findByName);
};

Well then, we're done. Now let's give main.js a haircut.

Refactor main.js

So, we now have a small and clean main.js file.

var express = require('express');
var app = express();
var bodyparser = require('body-parser');
var mongoose = require('mongoose');

app.use(bodyparser.urlencoded({
  extended: true
}));

app.use(bodyparser.json());

mongoose.connect('mongodb://localhost:27017/restaurant');

require('./app/routes.food')(app);

app.use(express.static(__dirname + '/public'));

app.set('port', process.env.PORT || 3001);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

If you followed along, the directory structure looks like this:

.
β”œβ”€β”€ app
β”‚Β Β  β”œβ”€β”€ controller.food.js
β”‚Β Β  β”œβ”€β”€ model.food.js
β”‚Β Β  └── routes.food.js
β”œβ”€β”€ main.js
β”œβ”€β”€ node_modules
β”‚Β Β  β”œβ”€β”€ body-parser
β”‚Β Β  β”œβ”€β”€ express
β”‚Β Β  └── mongoose
β”œβ”€β”€ package.json
└── public
β”œβ”€β”€ index.html

What's next?

Next up is authentication testing.

2 Replies to “Beginning Node.js – REST API with a Mongodb backend (refactoring) – part 4”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.