Node Walkthrough- Final Steps

Now you have a working server that talks to our mongoDB database. The user can make a GET request and see data about which movies have been added to the database. Now the last step is to allow users to create their own movies and add them to the database. Luckily, most of the hard work is finished and we only need to add 2 more controller functions!

Finishing our Controller

We're going to create two more routes: one for creating a new movie, and one for creating a new review. Open up mainController.js, and add the method below to our setupRoutes() function.

Remember how we set up the BodyParser middleware earlier? Because of that, the request body data from our users will be added to the request.body variable. So we create an object called dataToInsert and set it's title and description to whatever the user specified in the request body. Then we create a new Movie object using that data, and try to save it.

The save() method will trigger the callback we provide once it's finished running. If there was an error, we send back the error. Otherwise, we send the new movie to the client.

    /*
     * This function is called when the client makes a POST request to "/api/movies".
     * The movie data we need to insert is given to us in the request body. 
     * If the data is valid, we add that to our database. 
     */
    app.post('/api/movies', function(request, response) {
        /*
         * Collect the data we got from the client, and
         * insert it into a JSON object  
         */
        var dataToInsert = {
            title: request.body.title,
            description: request.body.description,
            image: request.body.image
        };

        /*
         * Create a new Movie from that data
         * using the mongoose Movie model. 
         */
        var newMovie = new Movie(dataToInsert);

        /*
         * Actually save our new movie to the database.
         * If we get an error, send that error to the client 
         * so they know what went wrong.  
         */
        newMovie.save(function(err) {
            if(err)
                response.send(err); //Print error if there was a problem
            else
                response.send(newMovie); //Send the client the new movie we just inserted
        });
    });

Now we just need to add one final method for creating movie reviews. The idea behind this function is very similar to the last. The difference is that now we need to find the movie that the user has specified, and then save the new review. We also use the :id in the url again just like before.

We use findOne() exactly like we did before. Instead of sending back movie data if there's no error, we add the review to the movie's review array using push(). Then we call save() again to update the database, and check to make sure there were no errors.

    /*
     * This function is called when the client makes a POST request to "/api/movies/:id/reviews".
     * The data we need to insert is given to us in the request body. 
     * We take that data and add it to the review array. 
     */
    app.post('/api/movies/:id/reviews', function(request, response) {

        var movieID = request.params.id; //Movie ID will be taken from the URL   
        /*
         * The data to use for the review will come from the request body.
         * We insert that data into a JSON object. 
         */
        var dataToInsert = {
            score: request.body.score,
            body: request.body.body
        };

        /*
         * Look up the movie this review is for.
         * We pass {_id: movieID} so mongoose knows
         * which movie to look for.  
         */
        Movie.findOne({_id: movieID}, function(err, movie) {
            /*
             * Make sure there was no error finding this movie. 
             * If there was, then the err variable will be set. 
             */
            if(err) {
                return response.sendStatus(500); //Send an error to client, and return so that the function stops here. 
            }

            /*
             * Add this review to the movie's array. 
             * Then save the movie like we did before. 
             */
            movie.reviews.push(dataToInsert);
            movie.save(function(err) {
                /*
                 * Make sure there was no error. Even though
                 * the movie exists, the user may have entered
                 * invalid data (like a negative score).  
                 */
                if(err)
                    response.send(err); //Print error if there was a problem
                else
                    response.send(movie.reviews[movie.reviews.length-1]);    //Send the client the new movie we just inserted
            });

        });
    });

And that's all the coding you need to do for the server! If you run your server, you should be able to add new movies and reviews using postman. Thanks to all the rules we set up in our movie schema, if you try to add invalid data you'll receive an error that explains what went wrong.

All Done!

That's it! You have a fully working (and very cool) API. Along the way you learned about cool technologies like NodeJS and MongoDB. You learned how to use awesome npm modules like Express and Mongoose. You even learned how to set up middleware like BodyParser and Cors. Pat yourself on the back and enjoy your awesome result!

Done early? Why not try using your new skills to make some extra routes! You can try adding a route to get the average score of a movie, or maybe the top 5 movies on the system.