In this challenge, you will add Tags to the Noteful app, populate the notes with tags, create routes and tests for the tags and update the routes and test for the notes.
- Create tag schema, update notes schema and then seed the database
- Create tags endpoints and update notes endpoints
- Update
server.js
to mount tags router - Update the client
Since you created a similar schema and model for Notes and Folders we will keep the instructions brief.
Create a /models/tags.js
file and create a tagsSchema
with the following specs:
- Create a
/models/tags.js
file for the Schema and Model. - Create a simple
tagSchema
and define aname
field with the following criteria:- Type is
String
- Required is
true
- Unique is
true
- Type is
- Create timestamps fields
createdAt
andupdatedAt
using the Mongoose timestamps option - Configure the Mongoose
toObject
option to transform the doc:- Include
virtuals
likeid
to show in the output - Suppress the
__v
version key - Delete the
_id
from the return object
- Include
- Create
Tag
model using thetagSchema
and export it
Next you will create Tags seed data and update Notes seed data with tags
.
- Create
/db/seed/tags.json
file - Add seed data like the following example.
[
{
"_id": "222222222222222222222200",
"name": "breed"
},
{
"_id": "222222222222222222222201",
"name": "hybrid"
},
{
"_id": "222222222222222222222202",
"name": "domestic"
},
{
"_id": "222222222222222222222203",
"name": "feral"
}
]
Now that you have defined a Tag Schema and Model, you can add a tags
field to the Notes Schema.
In /models/note.js
, update the noteSchema
as follows:
- Define a
tags
field:- Array of
ObjectId
- References
Tag
model
- Array of
tags: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Tag' }],
Let's update the notes.json
. Below is a sample note with its tags set to the _id
for foo
, bar
, and baz
. Update the sample data in your seed data file with tags
info
{
"_id": "000000000000000000000003",
"title": "7 things lady gaga has in common with cats",
"content": "Posuere sollicitudin aliquam ultrices sagittis orci a. Feugiat sed lectus vestibulum mattis ullamcorper velit. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Velit egestas dui id ornare arcu odio. Molestie at elementum eu facilisis sed odio morbi. Tempor nec feugiat nisl pretium. At tempor commodo ullamcorper a lacus. Egestas dui id ornare arcu odio. Id cursus metus aliquam eleifend. Vitae sapien pellentesque habitant morbi tristique. Dis parturient montes nascetur ridiculus. Egestas egestas fringilla phasellus faucibus scelerisque eleifend. Aliquam faucibus purus in massa tempor nec feugiat nisl.",
"folderId": "111111111111111111111101",
"tags": ["222222222222222222222200", "222222222222222222222201", "222222222222222222222202"]
},
Update the /utils/seed-database.js
file to insert tags and create an index. The index Tag.createIndexes()
call tells mongo to create an index immediately which is used enforce the unique rule on Tag names.
Below is a simple and reliable way to seed the database and trigger indexing. Update your /utils/seed-database.js
file to require the Tag model and seed data. And then update it to insert Tags and create an index as shown below.
// ... REMOVED FOR BREVITY
mongoose.connect(MONGODB_URI)
.then(() => mongoose.connection.db.dropDatabase())
.then(() => {
return Promise.all([
Note.insertMany(seedNotes),
Folder.insertMany(seedFolders),
Tag.insertMany(seedTags),
Folder.createIndexes(),
Tag.createIndexes()
]);
})
// ... REMOVED FOR BREVITY
Confirm the seed process worked correctly by verifying the data using Mongo shell or your favorite database GUI.
Your next challenge is to create Folder endpoints and integration tests.
Create a new /routes/tags.js
file to hold the endpoints and mount it on server.js
. In the file, create the following CRUD endpoints.
GET
all/tags
- Sort the response by
name
- Sort the response by
GET
/tags
byid
- Add validation that protects against invalid Mongo ObjectIds and prevents unnecessary database queries.
- Add condition that checks the result and returns a 200 response with the result or a 404 Not Found
POST
/tags
to create a new tag- Add validation that protects against missing
name
field - A successful insert returns a
location
header and a 201 status - Add condition that checks for a
duplicate key error
with code11000
and responds with a helpful error message
- Add validation that protects against missing
PUT
/tags
byid
to update a tag- Add validation which protects against missing
name
field - Add validation which protects against an invalid ObjectId
- Add condition that checks the result and returns a 200 response with the result or a 404 Not Found
- Ensure you are returning the updated/modified document, not the document prior to the update
- Add condition that checks for a
duplicate key error
with code11000
and responds with a helpful error message
- Add validation which protects against missing
DELETE
/tags
byid
deletes the tag AND removes it from thenotes
collection- Remove the tag
- Using
$pull
, remove the tag from thetags
array in thenotes
collection. - Add condition that checks the result and returns a 200 response with the result or a 204 status
GET
all/notes
- Add
tags
to the response - Use
.populate()
to populate the tags array - Capture the incoming
tagId
and conditionally add it to the database query filter
- Add
GET
/notes
by id- Add
tags
to the response - Use
.populate()
to populate the tags array
- Add
POST
/notes
- Capture
tags
from request body - Verify each tag id is a valid
ObjectId
and, if necessary, return a user-friendly response with a 400 status - Save
tags
along with the othernote
fields
- Capture
PUT
/notes
- Capture
tags
from request body - Verify each tag id is a valid
ObjectId
and, if necessary, return a user-friendly response with a 400 status - Save
tags
along with the othernote
fields
- Capture
DELETE
/notes
- No change :)
Create a /test/tags.js
file, the basic structure in similar to /test/folders.js
. Update the require statements and the Mocha life-cycle hooks to use Tag
models and tags seed data.
Create tests to verify the functionality of the /tags
endpoints. As your work through the tests, check the code coverage for clues on which aspects of your code you have validated and which still needs tests.
Don't forget to update /test/notes.js
. You added new features to these endpoints earlier and that functionality needs to be tested to ensure it continues to work properly.
- Update the require statements to include tags.
- Update the life-cycle hooks to seed the database with notes, folders and tags
- Update the tests to verify tag related features
Check your code coverage. Are there any lines of code which are not covered by tests? Create tests for any outstanding features.
Finally, uncomment the tags search on /public/index.js
.
Promise.all([
api.search('/api/notes'),
api.search('/api/folders'),
api.search('/api/tags')
])