Giter VIP home page Giter VIP logo

intermediate-node-course's People

Contributors

cpbange avatar grobergm avatar

Watchers

 avatar  avatar

intermediate-node-course's Issues

Set up node project

Hey there, fellow programmer!

Welcome to the Intermediate Node.js course! If you are taking this course, I am assuming you know the basics of Node.js and Express.js. If not, a good place to start is the intro to node and express course, here on GitHub Learning Lab.

In this tutorial, you will learn how to connect your server to a NoSQL database called MongoDB. You will also learn how to refactor repetitive code, to make it easier to maintain. By the end of this you have a Rest API that can Create, Read, Update, and Delete (CRUD) documents in MongoDB.

This is an interactive tutorial. At the end of each section, you will be prompted to do something to continue. If you don't get a response right away, try refreshing your browser.

Leave a comment about something you would like to Create, Read, Update, and Delete to continue

Create User model

Let's start by making a User model for mongodb using the mongoose library. This will be the template used to describe what each individual document will look like in our collection.

Find the "models" directory in the root of your project and open "User.js", then add this code to it:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true }
});

module.exports= mongoose.model('User',UserSchema)

Looks like a JS object doesn't it? That is one of the cool things about MongoDB, it is easy to transfer data from the frontend to the backend. Think of this as a factory, or mold, that can create new User documents in a User collection.

Looking at the model above, which key (name, email, or password) needs to have unique values?

Leave a comment with your answer to continue

Create, Read, Update, and Delete

CREATE: User.create

Let's start using this model to create some users.Insert the following code in the post route so it looks like this:

// CREATE
app.post('/users',(req,res)=>{
  User.create(
    {
      name:req.body.newData.name,
      email:req.body.newData.email,
      password:req.body.newData.password
    },
    (err,data)=>{
    if (err){
      res.json({success: false,message: err})
    } else if (!data){
      res.json({success: false,message: "Not Found"})
    } else {
      res.json({success: true,data: data})
    }
  })
})

When you want to make a new document in MongoDB, you can simply call the "create" method on your mongoose model. The first argument is an object containing the values for the new document (stored in req.body). The next argument is a callback function, which handles the response (res) from the database.

Testing

Ok let's test our code before we push it to GitHub. Start up Postman and set up a post request to: http://localhost:8000/users

Under the Headers tab, add this key/value pair:

Content-Type : application/json

Next, go to the body tab and select raw JSON, then paste this in the text under it:

{
  "newData":{
    "name":"Jim",
    "email":"[email protected]",
    "password":"secretPassword"
  }
}

Send the post request, and see if you get a successful response. If our route worked, you should get JSON data back with the new user under "data". Notice that there is an "_id" key automatically created.

Leave a comment with the value of the _id key to continue

Refactor

At this point, your server.js file should look something like this:

const express= require('express');
const mongoose= require('mongoose');
const bodyParser= require('body-parser');
const port=8000;
const app= express();

const User=require('./models/User');
mongoose.connect('mongodb://localhost/userData')

app.use(bodyParser.json());

app.listen(port, ()=>{
  console.log(`server is listening on port:${port}`)
})

app.post('/users',(req,res)=>{
  User.create(
    {
      name:req.body.newData.name,
      email:req.body.newData.email,
      password:req.body.newData.password
    },
    (err,data)=>{
      if (err){
        res.json({
          success: false,
          message: err
        })
      } else if (!data){
        res.json({
          success: false,
          message: "Not Found"
        })
      } else {
        res.json({
          success: true,
          data: data
        })
      }
    }
  )
})

app.route('/users/:id')
.get((req,res)=>{
  User.findById(
    req.params.id,
    (err,data)=>{
      if (err){
        res.json({
          success: false,
          message: err
        })
      } else if (!data){
        res.json({
          success: false,
          message: "Not Found"
        })
      } else {
        res.json({
          success: true,
          data: data
        })
      }
    })
})
.put((req,res)=>{
  User.findByIdAndUpdate(
    req.params.id,
    { 
      name:req.body.newData.name,
      email:req.body.newData.email,
      password:req.body.newData.password
    },
    {
      new:true
    },
    (err,data)=>{
      if (err){
        res.json({
          success: false,
          message: err
        })
      } else if (!data){
        res.json({
          success: false,
          message: "Not Found"
        })
      } else {
        res.json({
          success: true,
          data: data
        })
      }
    })
})
.delete((req,res)=>{
  User.findByIdAndDelete(
    req.params.id,
    (err,data)=>{
      if (err){
        res.json({
          success: false,
          message: err
        })
      } else if (!data){
        res.json({
          success: false,
          message: "Not Found"
        })
      } else {
        res.json({
          success: true,
          data: data
        })
      }
    })
})

This code works, but it is pretty repetitive. In general, it is a good practice to refactor code like this so it is easier to maintain.

Create function for response

We are handling the response in the same way each time. We should define a function to shorten this and make it easier to maintain. Paste this in your server file above your routes:

function sendResponse(res,err,data){
  if (err){
    res.json({
      success: false,
      message: err
    })
  } else if (!data){
    res.json({
      success: false,
      message: "Not Found"
    })
  } else {
    res.json({
      success: true,
      data: data
    })
  }
}

Now, let's call the "sendResponse" function in our mongoose callback functions:

app.post('/users',(req,res)=>{
  User.create(
    {
      name:req.body.newData.name,
      email:req.body.newData.email,
      password:req.body.newData.password
    },
    (err,data)=>{sendResponse(res,err,data)}
  )
})

app.route('/users/:id')
.get((req,res)=>{
  User.findById(
    req.params.id,
    (err,data)=>{sendResponse(res,err,data)})
})
.put((req,res)=>{
  User.findByIdAndUpdate(
    req.params.id,
    { 
      name:req.body.newData.name,
      email:req.body.newData.email,
      password:req.body.newData.password
    },
    {new:true},
    (err,data)=>{sendResponse(res,err,data)})
})
.delete((req,res)=>{
  User.findByIdAndDelete(
    req.params.id,
    (err,data)=>{sendResponse(res,err,data)})
})

You can always replace the generic sendResponse function with a custom callback, if you need more flexibility.

Using spread syntax (...)

We can shorten these routes further by using the JavaScript spread syntax, which copies each key/value pair in our newData object.

So, rather than this:

{
  name:req.body.newData.name,
  email:req.body.newData.email,
  password:req.body.newData.password
}

we can write this:{...req.body.newData}.

Our routes should look like this now:

app.post('/users',(req,res)=>{
  User.create(
    {...req.body.newData},
    (err,data)=>{sendResponse(res,err,data)}
  )
})

app.route('/users/:id')
.get((req,res)=>{
  User.findById(
    req.params.id,
    (err,data)=>{sendResponse(res,err,data)})
})
.put((req,res)=>{
  User.findByIdAndUpdate(
    req.params.id,
    {...req.body.newData},
    {new:true},
    (err,data)=>{sendResponse(res,err,data)})
})
.delete((req,res)=>{
  User.findByIdAndDelete(
    req.params.id,
    (err,data)=>{sendResponse(res,err,data)})
})

The code above is much easier to maintain. Also, with the spread syntax you only need to include values that are being changed. In the first version we were explicitly looking for a value at each key to update. If the values were not included, they would be set to "null". Now our routes are more flexible, since the object to update is defined by the request. This might seem weird at first, but the model should keep your data consistent.

Test this in Postman to make sure you refactored correctly. When you are finished, commit these changes and push to GitHub.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.