Pt3 Building a food order system with MEAN Stack (MongoDB, Express, AngularJs and NodeJs).

in #utopian-io6 years ago (edited)

In our Last tutorial, we started by creating the model of our users, we also explained the concept of token based authentications with passport and Jwt token. Not forgeting, Our routes, controller, and model for the user was put in place along with the authentication mechanism for the user controller.

Overview.

Now we have our user model ready, in this installment, we are going to add some new methods and function for our users. We are alsso going to create our item model Route and some controller method.

Requirement.

  • Typescript version 2.4.2
  • Node version version 8.9.4
  • Npm version 5.6.0
  • Express version ^4.15.3.
  • Postman
  • Voltron Server Repository

Table of content.

  1. Adding New methods to the user controller.
  2. Creating the Item model.
  3. Creating the item Routes and Controller.
  4. Adding methods to the Item Controller.

Difficulty

This tutorial is rated intermediate.

Adding New methods to the user controller.

If you remember, in our Last tutorial, we created some end-points for our users which request can be sent to from our front-client. If you can remember, we added to endpoints;

  • The End-point to Create a User.
  • The End point to Authenticate a user with JWT token.

What End-points would be added? yeah, i remember we are to add three Endpoints

  • The End point to get a single user from the db
  • The End point to get all users.
  • Lastly the point to update any property in the users' Object.

Lets Start withe End-point responsible for return a single item from the database.
Its quite simple, all we need to do is find a unique identifier in the database like id, username and email.

The End point to get a single user from the db

public static async getUser(req: Request, res: Response, next: NextFunction) {

        try {

            // 
            // Get data
            const username: String = req.params.username;
            let result = await UserModel.findOne({ username }).exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'Successfull got a user',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not get Examples',
                err: err
            });
        }
    }

In the above, we are using the asyc and await to wait for the actual data it arrive. We are simply just hoping the data will arrive. This is what is called asyncronous. We get the user input (username), used the username to find through the model for the said user and return the response. If an error occur, return the message in the catch block.

The End-point to get all users.

The End-point to get all users is almost thesame as the one for a single user. the differnce is the method used on the user model. The method on the model is find().
exec() returns a promise when the find() methodis ran on the UserModel.

public static async getAll(req: Request, res: Response, next: NextFunction) {

        try {

            // 
            // Get data
            let result = await UserModel.find().exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'it works! We got all users',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not get Users',
                err: err
            });
        }
    }

    /**
     * getUser 
     * @param {*} req 
     * @param {*} res  
     * @param {*} next 
     */

The response area simply checks for code for error and respond according.

The End-point to update any property in the users' Object.

Finally on our UserController, lets work on the update method to change any value on the UserModel or object. We are going to be making use of the object spread operator for object object simple by adding to the object.

Firstly we search for the user usinng the request from the body of what was entered by the user, of which was the username of the user, next we use use spread object operator to to update the model with what was entered from the user request body.

Note: The method for updating on the model is findOneAndUpdate() it accepts the parameter that can be used to find an item in the model.

const username: String = req.params.username;
            let result = await UserModel.findOneAndUpdate({ username }, {
                ...req.body,
                updatedAt: new Date()
            }).exec();

Okay we updated the object, we can now save the status code and respond with the status code showing an appropriate message.

        
        try {

            // 
            // Get data
            const username: String = req.params.username;
            let result = await UserModel.findOneAndUpdate({ username }, {
                ...req.body,
                updatedAt: new Date()
            }).exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'Sucessfully updated a user',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not create the user',
                err: err
            });
        }
    }

Finally all our user methods are implemented in the UserController.
Before we forget lets add the route for our new UserController method.

Go to api/user/user.route.ts and Update the the route file.

import { Router, Request, Response, NextFunction } from 'express';
import UserController from './user.controller';

export class UserRouter {

    public router: Router


    /*--------  Constructor  --------*/


    constructor() {

        // 
        // Set router
        this.router = Router();
        this.init();
    }


    /*--------  Methods  --------*/


    /**
     * Init all routes in this router
     */
    init () {
        this.router.put('/:username', UserController.update);
        this.router.get('/', UserController.getAll);
        this.router.get('/:username', UserController.getUser);
        this.router.post('/', UserController.create);
        this.router.post('/authenticate', UserController.authenticate);
    }

}

// 
// Create Router and export its configured Express.Router
// new UserRouter().init();

export default new UserRouter().router;

Noticed in the init method, we added some new route which uses different protocol.
which are PUT and GET.

Building the Item model.

We just finished the whole UserController. Next up is the items, so what does the item need?
The item model needs the followng property

  • id
  • title
  • type
  • desc
  • price
  • photo
  • inStock
  • createdAt
  • updatedAt
  • deletedAt

id ---The id is generated by the mongodb and its unique for each item, which is an object
title--- The title of the item e.g Fried Rice, wwhich accepts a string
type--- The type which is a string e.g drink, food
desc--- This accepts a string and shows a short discription of the food.
photo--- This accepts a string, which shows the location of the image in the pubic or assets folder.
inStock--- This is the number of item avialable at a given time, its accepts the type number.
createdAt--- This is the exact time an item was inserted into the db it accepts a type of Date
updatedAt--- The exact time an item in the db was modified.
deletedAt --- As it implies.
In api/item, create a file called item.model.ts and add the code for building the model.

import { Schema, model } from 'mongoose';

let ItemSchema: Schema = new Schema({
    id: {
      type: Number,
    },
    title: {
        type: String,
        required: true,
        unique: true
      },
    type: {
        type: String,
        required: true,
        default: ''
      },
    desc: {
        type: String,
        default:'',
      },
    price: {
        type: Number,
        required: true
    },
    photo: {
        type: String,
        default: ''
      },
    inStock: {
    type: Number,
    default: 0,
    required: true
    },
    createdAt: {
      type: Date,
      default: new Date
    },
    updatedAt: {
      type: Date,
      default: new Date
    },

    deletedAt: {
        type: Date,
      },
});




export default model('Item', ItemSchema);

As usual, we import schema and model from mongoose in line 1.
and export the model at the last line.
hTake note: On the Schema, we have some prroperties like dafault
and required. these are used to prefill and validate the entry to the db respectively.

Building the item Route.

Firstly, we need to create the prefix for our route in the main routes.ts file which is found on the config folder.
update the setAllRoutes method

 private setAllRoutes() {
        this.app.use('/api/users', UserRouter);
        this.app.use('/api/items', ItemRouter);
    }

Now we have a prefix for our item route called localhost/api/items/.

Next up the item.route.ts, create this file in the api/item if not created.
Here, we need to add all the routes for initiating actions for our controller with different protocol.

import { Router, Request, Response, NextFunction } from 'express';
import ItemController from './item.controller';

export class ItemRouter {

    public router: Router


    /*--------  Constructor  --------*/


    constructor() {

        // 
        // Set router
        this.router = Router();
        this.init();
    }


    /*--------  Methods  --------*/


    /**
     * Init all routes in this router
     */
    init () {
        this.router.put('/:_id', ItemController.updateItem);
        this.router.get('/', ItemController.getAll);
        this.router.get('/:_id', ItemController.getItem);
        this.router.post('/', ItemController.createItem);
        this.router.delete('/:_id', ItemController.deleteItem);
    }

}

// 
// Create Router and export its configured Express.Router
// new UserRouter().init();

export default new ItemRouter().router;

The first line import { Router, Request, Response, NextFunction } from 'express'; imports all the modules listed in the curly brace from express. We also imported our itemController which we have not created yet.

In the constructor method, we are instantiated a new router, and an init() method that kicks up very route.

Lets talk about the route in the init method.
this.router.put('/:_id', ItemController.updateItem);
The above route would show something like localhost:3000/api/items/12sdfffcvgfddszd which uses the PUT protocol to update an item property in the db it uses the itemController method updateItem for the logic, where 12sdfffcvgfddszd is the id of the item in the db.

this.router.get('/', ItemController.getAll);
this.router.get('/:_id', ItemController.getItem);

The above two routes uses the GET protocol to retrieve data from the db the first route localhost:3000/api/item uses the getAll method of the itemController to show all item in the db.
while the second, also uses the get protocol but uses the id of the item to return a particular item.

this.router.post('/', ItemController.createItem);
this.router.delete('/:_id', ItemController.deleteItem);

The first route this.router.post('/', ItemController.createItem); uses the post protocol to add items to the db and it uses the method createItem while the last uses the id to filter through the db and uses the DELETE protocol to remove an item from the db.

Building the itemController.

We have been using methods and imported a controller that did not yet exist, so lets create the item controller and its methods.
Create the file item.controller.ts in api/item folder and add the code below.

import { Request, Response, NextFunction } from 'express';
import Model from './item.model';

export default class UserController {

    /**
     * Get all
     * @param {*} req 
     * @param {*} res 
     * @param {*} next 
     */
    public static async getAll(req: Request, res: Response, next: NextFunction) {

        try {

            // 
            // Get data
            let result = await Model.find().exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'it works! We got all items',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not get items',
                err: err
            });
        }
    }

    /**
     * getUser
     * @param {*} req 
     * @param {*} res 
     * @param {*} next 
     */

    public static async getItem(req: Request, res: Response, next: NextFunction) {

        try {

            // 
            // Get data
            const id: String = req.params._id;
            let result = await Model.findOne({ id }).exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'Successfull got an item',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not get item',
                err: err
            });
        }
    }

    /**
     * Create
     * @param {*} req 
     * @param {*} res 
     * @param {*} next 
     */
    public static async createItem(req: Request, res: Response, next: NextFunction) {
        
        const title:String = req.body.title;
        const id:Number = req.body.id;
        const type:String = req.body.type;
        const desc:String = req.body.desc;
        const photo:String = req.body.photo;
        const price:Number = req.body.price;
        const inStock:Number = req.body.inStock;
    

        // Create model
        let model = new Model({
            id,
            title,
            type,
            desc,
            photo,
            price,
            inStock
        });
        // 
        // Save
        await model.save();

        res.send({
            message: 'Created!',
            model: model
        });
    }

    public static async deleteItem(req: Request, res: Response, next: NextFunction) {
        const _id:String = req.params;
        
        try {

            // 
            // Get data
            const username: String = req.params._id;
            let result = await Model.findOneAndRemove({ _id }, {
                ...req.body,
                deletedAt: new Date()
            }).exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'Sucessfully deleted item',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not delete th item',
                err: err
            });
        }
    }

    public static async updateItem(req: Request, res: Response, next: NextFunction) {
        const _id:String = req.params;
        
        try {

            // 
            // Get data
            const username: String = req.params._id;
            let result = await Model.findOneAndUpdate({ _id }, {
                ...req.body,
                updatedAt: new Date()
            }).exec();
            const status = res.statusCode;

            // 
            // Response
            res.send({
                message: 'Sucessfully updated item',
                result: result,
                status: status
            });
        } catch (err) {

            // 
            // Error response
            res.send({
                message: 'Could not create th item',
                err: err
            });
        }
    }
}

itemController Explaination.

We started by importing the item schema and Request, Response, NextFunction from express
we create the userController class and add the methods which we created on the routes. which are:

  • getAll()
  • getItem()
  • createItem()
  • deleteitem()
  • updateItem()

Lets start with the getAll method, which returns all the items in the db using the find() method on the item model.

We execute this code in a try and catch block and show the appropriate error from the model.

getItem method

This method uses the find() and accepts a property in the db, the id of the object is used to find through the db and return a specific item.

create item method.

sets all the input from the body( data entered by the user), validation is ran on the data and saved using the method model.save

update item method

Uses the method findOneAndUpdate() which accepts the _id of the item that needs to be updated using the objected spread operator, the data from the body is save and updated.

let result = await Model.findOneAndUpdate({ _id }, {
                ...req.body,
                updatedAt: new Date()
            }).exec();

delete item method

The method uses findOneAnd Remove() method from the db and accepts the id of the item and using the object spread operator the item need to be deleted from the body is initiated

let result = await Model.findOneAndRemove({ _id }, {
                ...req.body,
                deletedAt: new Date()
            }).exec();

Conclusion

We just concluded the users and the items end-points for all request to our server, in the next part, we would build the orders model controller and route and use postman for testing our request, stay tune.

Curriculum



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thanks for the contribution.


Need help? Write a ticket on https://support.utopian.io.
Chat with us on Discord.

[utopian-moderator]

Hey @sirfreeman! Thank you for the great work you've done!

We're already looking forward to your next contribution!

Fully Decentralized Rewards

We hope you will take the time to share your expertise and knowledge by rating contributions made by others on Utopian.io to help us reward the best contributions together.

Utopian Witness!

Vote for Utopian Witness! We are made of developers, system administrators, entrepreneurs, artists, content creators, thinkers. We embrace every nationality, mindset and belief.

Want to chat? Join us on Discord https://discord.me/utopian-io

Loading...

Coin Marketplace

STEEM 0.30
TRX 0.11
JST 0.033
BTC 63968.82
ETH 3136.80
USDT 1.00
SBD 4.28