Skip to content

Latest commit

 

History

History
130 lines (90 loc) · 5.33 KB

sprint3.md

File metadata and controls

130 lines (90 loc) · 5.33 KB

Sprint 3 - Embedded documents

1. Many unique characters belong to each book!

That's right: we're going to add Characters to each of the books. Characters, however, are usually pretty unique to the book that they're in, so we'll be using an embedded document; embedding Character into the Book schema.

  1. Commit your work (so that you don't overwrite your old work).
  2. Run git checkout starting-point-sprint-3 to get the updated code that includes a frontend for characters. Inspect the solutions, especially the POST api/books route to see how to handle the case when an author is not yet saved in the database.
  3. From here, git checkout -b my-work-sprint-3.
  4. Startup the app making sure to node seed.js and node server.js.
  5. Take a look at the current UI in your web browser. You should see that a new field has been added to each book listed.
  6. Open your web browser developer tools. Try to add a character to one of the books. You should see an error message like: jquery.min.js:4 POST http://localhost:3000/api/books/56fc1e8a8d4bcdb3e5e0092e/characters 404 (Not Found)
  • What type of error is 404?

2. Creating the CharacterSchema

Since Characters will be embedded we can create it's schema either in its own file or in the same file as the document it will be embedded in. Let's keep it simple this time; and create it in the the models/book.js.

  1. Add the CharacterSchema to models/book.js with one name attribute (keeping it simple for now).
// models/book.js
var CharacterSchema = new Schema({
  name: String
});
  1. Now take a look at the BookSchema. Our current schema doesn't have any way of storing Character data. Let's include characters using that Character Schema.

Do you remember how to access an embedded Schema?

don't remember? click here
characters: [CharacterSchema]  // for multiple embedded items in an array
mainCharacter: CharacterSchema // if you want one embedded item

3. POST characters

At this point your Book model should be making use of Characters. But since we haven't added anything to server.js yet, those characters can't be added by users and stored in the DB.

Since characters are part of Books we'll setup our URLs to reflect that.

Example:

METHOD ROUTE DESCRIPTION
GET /api/books/:bookId/characters get all the characters for this book
POST /api/books/:bookId/characters add a new character to the book
GET /api/books/:bookId/characters/:id get a specific character from this book
PUT /api/books/:bookId/characters/:id update a character from this book
DELETE /api/books/:bookId/characters/:id delete a character from this book

We don't need all of these today; in fact we're only really going to worry about adding characters for now.

  1. Add a new route to server.js:
app.post('/api/books/:book_id/characters', function (req, res)
  1. See if you can get the book (findById) and then push the character into the book's characters array. If the format fits, Mongoose will convert the object to a Character for you. Finally you need to save the book and return the entire book as json. (note that author is still a part of this so you'll need to populate it too.)

Let's use this psuedo-code as an example:

// Create a character associated with a book
app.post('/api/books/:book_id/characters', function (req, res) {
  // Get book id from url params (`req.params`)
  var bookId = req.params.book_id;
  db.Book.findById(bookId)
    .populate('author')
    .exec(function(err, foundBook) {
      // handle errors
      // push req.body into characters array

      // save the book with the new character
      // send the entire book back
      }
    }
  );
});
Spoiler
 // Create a character associated with a book
 app.post('/api/books/:book_id/characters', function (req, res) {
   // Get book id from url params (`req.params`)
   var bookId = req.params.book_id;
   db.Book.findById(bookId)
     .populate('author') // Reference to author
     // now we can worry about saving that character
     .exec(function(err, foundBook) {
       console.log(foundBook);
       if (err) {
         res.status(500).json({error: err.message});
       } else if (foundBook === null) {
         // Is this the same as checking if the foundBook is undefined?
         res.status(404).json({error: "No Book found by this ID"});
       } else {
         // push character into characters array
         foundBook.characters.push(req.body);
         // save the book with the new character
         foundBook.save();
         res.status(201).json(foundBook);
       }
     }
   );
 });

4. Does it work yet? Does it work yet?

  1. Give it a shot now; the UI should just work. If not make use of debugger or console.log messages to try and resolve any issues.

  2. We haven't pre-built any UI to make use of embed anywhere else, but if you have spare time you could try to work on the server-side for GET characters or DELETE characters. Maybe you can even add a delete button to the UI next to each character.