logo_ironhack_blue 7

Mongoose Movies

Introduction

Everyone likes celebrities, right? Well, even if you don't, now is your chance to create your own, better, fictional celebrities! Let's create an Express app with all the basic CRUD actions that will allow the user to create their own celebrities and edit them as they see fit.

The user should be able to:

1. See the list of celebrities
2. See the details of a celebrity
3. Add new celebrities
4. Update existing celebrities
5. Delete celebrities

But wait! That's not all!

Once we have our celebrities, we need something for them to do! Let's make up some movie ideas for our celebrities to star in.
That means we'll need all the basic CRUD actions for movies as well.

The user should be able to:

6. See the list of movies.
7. See the details of a movie.
8. Add new movies.
9. Update existing movies.
10. Delete movies.

Requirements

  • Fork this repo
  • Clone this repo

Submission

  • Upon completion, run the following commands:
$ git add .
$ git commit -m "done"
$ git push origin master
  • Create Pull Request so your TAs can check up your work.

Instructions

Iteration 0 | Initialize the project

After forking and cloning the project, you will have to add a .env file with some environment variables:

NODE_ENV=development
PORT=3000
MONGODB_URI=mongodb://localhost:27017/lab-mongoose-movies

And you have to install all the dependencies:

$ npm install

To make your life easier, we've added a development script to the package.json file. Instead of having to run node index.js every time you make an update, you can run the following command (that uses the package nodemon behind the scenes):

$ npm run dev

Before solving the lab, you'll need to import a few pre-existing celebrity documents into your database. This process is commonly called seeding the database (seeding is the process in which you add some initial records into the database). To do so, follow these steps:

  1. Open MongoDB Compass and connect to MongoDB.
  2. Press "Create Database". In the field for "Database Name", insert "lab-mongoose-movies", the same name we have concatenated into the variable MONGODB_URI in our .env file. In the field "Collection Name", write celebrities. Click on "Create Database".
  3. Use the interface to navigate to the database you have just created. Open the collection celebrities.
  4. Click on "Add Data", select "Import File", and use the file picker to navigate to the lab's directory. Select the file demo-celebrities.json, and choose "JSON" as the input file type. Click on "Import". You can also use the mongoimport command line tool to achieve the same purpose.

Afterwards, check the database with the MongoDB Compass to confirm that your data was saved.

Now you are ready to start 🚀

Iteration #1: The Celebrity Model

Once we have generated our Express app, our first step is to create the Celebrity model and seed some initial celebrities in our database.

The Celebrity model should have:

  • name - String (like Tom Cruise, BeyoncĂ©, Daffy Duck, etc.).
  • occupation - String (what the celebrity does, why they are famous. For example actor, singer, comedian, or you can put unknown if your celebrity is someone like Kim Kardashian).
  • catchPhrase - String (every celebrity needs a good catch phrase. Well maybe not all of them have one in real life, but all of our celebrities will have a catch phrase. This can be pretty much anything).

Steps we will follow in this iteration:

  1. Create the celebrity.js model file in the models/ folder.
  2. In the celebrity.js model file:
    • Create the celebrity schema with the properties name, occupation and catchPhrase.
    • Create the Celebrity model with the schema.
    • Export the Celebrity model.

Iteration #2: Listing Our Celebrities

Now that we've got some celebrities in the database, we can start working with them in our Express app. Let's display a list of all the celebrities.

Here's the route we will be using:

Route HTTP Verb Description
/celebrities GET Show all celebrities

Steps we will follow in this iteration:

  1. Locate the /celebrities GET route in routes/celebrities.js.
  2. In the route handler:
    • Call the Celebrity model's find static to retrieve all the celebrities.
    • If there's an error, call the route's next function and return the error.
    • If there isn't an error, render the celebrities/index view.
    • Pass the array of celebrities into the view as a variable.
  3. Create the celebrities/ folder inside views/.
  4. Create the index.hbs view file inside the views/celebrities/ folder.
  5. In the views/celebrities/index.hbs view file:
    • Add an <h2> tag for the page's heading.
    • Use a #each loop to display tags with each celebrity's name.
  6. In the views/index.hbs (homepage) file:
    • Add a link that goes to the /celebrities route.

Iteration #3: The Celebrity Details Page

We've got a list of celebrities that displays each name, but what if we want to see the other details? In our views/celebrities/index.hbs view, let's add links so that the user can click on any celebrity's name, and go to a page specifically for that celebrity. On this page, we will show all the details of that celebrity.

Here's the route we will be using:

Route HTTP Verb Description
/celebrities/:id GET Show a specific celebrity

Steps we will follow in this iteration:

  1. Create the /celebrities/:id GET route in routes/celebrities.js.
  2. In the route handler:
    • Call the Celebrity model's findOne or findById static to retrieve the details of a specific celebrity by its id.
    • If there's an error, call the route's next function and return the error.
    • If there isn't an error, render the celebrities/show view.
    • Pass the variable with the celebrity's details into the view.
  3. Create the show.hbs view file inside the views/celebrities/ folder.
  4. In the views/celebrities/show.hbs view file:
    • Add an <h2> for the page's heading.
    • Display tags with the celebrity's name, occupation and catchPhrase.
  5. In the views/celebrities/index.hbs view file:
    • As part of the loop that displays each celebrity's name, add a link that goes to the /celebrities/:id route with the :id replaced by the actual celebrity's id.

Iteration #4: Adding New Celebrities

Now that we have a list of celebrities, as well as a personalized details page for each celebrity, let's make it so the user can add new celebrities to the database

Route HTTP Verb Description
/celebrities/create GET Show a form to create a celebrity
/celebrities POST Post the data to this route to create a new celebrity document on database

Steps we will follow in this iteration:

  1. Locate the /celebrities/create GET route in routes/celebrities.js:
  2. In that route's handler:
  • Render the celebrities/create view.
  1. Create the create.hbs view file inside the views/celebrities folder
  2. In the views/celebrities/create.hbs view file:
    • Add an <h2> for the page's heading.
    • Add a <form> tag that makes a POST request to /celebrities.
    • Add <input> tags inside the form so the user can fill in values for each attribute of the celebrity. Make an input for name, occupation, and catchPhrase
    • Add a <button> tag in the form so the user can submit the form once they are done filling it out.
  3. Locate the /celebrities post route in routes/celebrities.js.
  4. In that route's handler:
    • Create an object with keys for name, occupation, and catchPhrase.
    • Values for those keys should come from the form (req.body is the object that contains the values resulting from the form for).
    • Create an instance of the Celebrity model with the object you made in the previous step.
    • Call the save method to save the new celebrity to the database.
    • If there is an error, render the celebrities/create view so the user can try again.
    • If there is no error, redirect to the page with the list of celebrities.
  5. In the views/celebrities/index.hbs view file:
    • Add a link that goes to the page you just created with the form to create a new celebrity.

Iteration #5: Deleting Celebrities

Now that we have a list of celebrities, a celebrity details page, and a page to create new celebrities, we only have 2 features left to implement: editing celebrities and deleting them. Since deleting is simpler, let's start with that.

Route HTTP Verb Description
/celebrities/:id/delete POST Delete a specific celebrity

Steps we will follow in this iteration:

  1. In the views/celebrities/index.hbs file:
    • As part of the loop, add a <form> tag that makes a POST request to celebrities/:id/delete where the :id is replaced by the actual id of each celebrity.
    • Add a <button> tag inside the form so that it can be submitted.
  2. Create the /celebrities/:id/delete POST route in your routes/celebrities.js file.
  3. In that route's handler:
    • Use the Celebrity model's findByIdAndRemove static to delete the celebrity by its id.
    • If there's an error, call the route's next function and return the error.
    • If there is no error, redirect to the list of celebrities page.

Iteration #6 (Bonus): Editing Celebrities

Final piece of our CRUD puzzle: editing existing celebrities.

Here are the routes we will be using:

Route HTTP Verb Description
/celebrities/:id/edit GET Show a form to edit a celebrity
/celebrities/:id POST Send the data from the form to this route to update and save the celebrity from the database

Steps we will follow in this iteration:

  1. Create the /celebrities/:id/edit GET route in routes/celebrities.js.
  2. In that route's handler:
    • Call the Celebrity model’s findOne or findById static to retrieve a specific celebrity by their id.
    • If there's an error, call the route's next function and return the error.
    • If there isn't an error, render the celebrities/edit view.
    • Pass the variable with the celebrity’s details into the view.
  3. Create the edit.hbs view file inside the views/celebrities/ folder.
  4. In the views/celebrities/edit.hbs view file:
    • Add an <h2> tag for the page's heading.
    • Add a <form> tag that makes a POST request to /celebrities/:id with the :id replaced by the actual celebrity's id.
    • Add <input> tags inside the form for each attribute of the celebrity.
      • Bonus: When you render the edit form, make sure each of the input fields is pre-filled with the current value of the attribute for that celebrity
    • Add a <button> tag inside the form so that the user can submit the form once they are done editing.
  5. Locate the /celebrities/:id POST route in the routes/celebrities.js file.
  6. In that route's handler:
    • Create an object with keys for each attribute of a celebrity (celebrity has 3 attributes. What were they again? Look back and review if you forgot).
    • Values for those keys should come from the form submission (req.body).
    • Call the Celebrity model’s update static and use the celebrity's id to specify which celebrity we are updating. Pass it the object with the new attributes as the second argument.
    • If there is an error retrieving that celebrity, call the route's next function and return the error.
    • If there is no error, redirect back to the list of celebrities.

Celebrities - Done!

At this point, we have implemented all the basic CRUD actions for the Celebrity model in our app. Nice work!

Now that we've done all this good work, it's time to do it all over again, but for the Movie model. After all, what's the point of having all these celebrities if we can't make up fake movies to cast them in?

We are going to create a Movie model and implement all the same CRUD actions for this model as well. Don't worry, it's really much easier the second time around.

Iteration #7: The Movie Model

Let's jump right in.

First of all, we'll need to create the Movie model.

The Movie model should have:

  • title - String
  • genre - String
  • plot - String

Steps we will follow in this iteration:

Go back and review what you did to create the Celebrity model. You'll need to create a file for the model, and in that file, you'll need to create a schema for the model as well.

Once you've done that, go to your seed.js file and either delete or comment out the seeds you made before for your celebrities. Replace these seeds with seeds for fake movies. If you don't delete/comment what you had before, when you run the seeds file with the node command in the terminal, it will create duplicates of all your celebrities.

Afterward, check the database with the MongoDB Compass to confirm that your data was saved.

Iteration #8: Listing Our Movies

Now that we've got some movies in the database, let's make a page where we list all our movies, just like we did with the Celebrity model.

Steps we will follow in this iteration:

Go back and review how you did this for the Celebrity model. You'll need to

  • Create a route.
  • Create a view file (and a folder for all your movies view files).
  • Use a database query to retrieve all the movies in your database and render the view.
  • Use a #each loop to display all your movies on that page.
  • Add a link to the page you just created on the home page so the user can navigate to it.

Iteration #9: The Movie Details Page

Now that we've got a list of movies, let's add a details page for each movie just like we did with our celebrities.

Steps we will follow in this iteration:

Go back and review what you did for the Celebrity model. You'll need to:

  • Create a route.
  • Use a database query to retrieve the specific movie that was clicked by the user.
  • Pass that movie into the view as a variable.
  • Create the view file.
  • In the view, display all the details of the movie.
  • On the Movies index page, make each movie a link to its own details page.

Iteration #10: Adding New Movies

Okay, the next step is to make it so the user can add new movies to the database.

Steps we will follow in this iteration:

Review how you did this for the Celebrity model.

  • Create 2 new routes, one to render page with the form on it, and one to send the data to after the form is filled out.
  • Create a view file to render the form.
  • Make sure the form is making a POST request to the other route you just created.
  • In your post route, create an object with all the info you just received from the form (remember, req.body).
  • Use this object to create a new movie and save it to the database and redirect back to the page with your list of movies.
  • Make sure to add a link to the form on the movies index page.

Iteration #11: Deleting Movies

Okay, only 2 features left, deleting and editing.

Steps we will follow in this iteration:

Review how you did this with the Celebrity model.

  • Add a button (inside of a form) next to each movie in your movies index page.
  • Create a route.
  • Use a database query to retrieve the Movie that was just clicked, and delete it from the database.

Iteration #12 (Bonus): Editing Movies

Final piece of our CRUD puzzle: editing existing movies.

Steps we will follow in this iteration:

Review how you did this for the Celebrity model.

  • Create 2 routes, one to display a form, and another to receive the data from that form.
  • Create a view file to display the edit form.
  • Use a database query to retrieve one movie from the database and pass that movie into the page with the form on it.
  • Render the view with the form, and pre-fill all the input fields with the current info about that movie.
  • Make sure your form is submitting a POST request to the other route you just created.
  • When the form is submitted, receive the data from the form and create an object with all the info.
  • Make a database query to retrieve the movie from the database and update the movie with the object you just created with all the info from the form.
  • Make sure you add a link to the edit page on your movies index page.

That's it!

Happy Coding! đź’™