Saving cat happiness to the database! This exercise will give you extra practice using mongoose, and will get you more familiar with the User
model.
Visit your profile (or someone else's profile). You can click on the profile picture to increase cat happiness (already implemented in workshop 2).
But now, when you referesh, your cat happiness is still there! You can also visit someone else's profile and increase their cat happiness permanently.
Run the following commands
git clone https://github.com/weblab-workshops/catbook-happiness.git
cd catbook-happiness
npm install
npm start
npm run hotloader # in a separate window
For every user, we want to store their cat happiness to the database.
Modify the file server/models/user.js
and add the following field to the schema:
cat_happiness
(its type isNumber
)
When a new user signs up, their cat_happiness
should be initialized to 0. To do this, you can modify auth.js
and add cat_happiness: 0
to newUser
(inside of getOrCreateUser()
).
But you still might run into an issue. When your user document was created during workshop 6, we hadn't added this in yet. That means, in your user document right now, cat_happiness === undefined
. This is a problem! We want your happiness to start at 0
, not undefined
.
Fortunately, mongoose has an convenient solution. You can specify a default value for a schema field, so if cat_happiness
was never set, it will automatically default to 0
when you try to use it.
Add a default value to the cat_happiness
field. You can view the mongoose documentation.
We need a new API route, so that whenever the user clicks on their profile picture, we increase the value of cat_happiness
stored in the database. Here is the specification (i.e. the requirements) for this route:
- POST
/api/cat-happiness
- When this route is called, increase the specified user's cat happiness by 1.
- Parameters -
userId
: the ID of the user whosecat_happiness
to increment - Returns:
{ cat_happiness: (the updated value) }
Implement this behavior. This may come in handy: http://weblab.to/mongo-snippets
Now, let's hook it up to the frontend. This will only involve changing one file: Profile.js
. Using our new endpoint, modify this file so that cat happiness is preserved when you refresh the page. If you don't know where to start, check out these hints.
Then, you're done! The result should look like the gif at the top of this page.
We'll need to modify this, so that instead of simply adding 1 to the state, we instead send a POST
request to our new endpoint.
To view final solution for this assignment:
# save your changes first by committing to git
git add .
git commit -m "my changes"
# view the completed code
git checkout complete
# to go back to viewing your work, you can type:
git checkout master
In the branch complete
, the code basically works, but there are a few tricky cases where stuff might go wrong. Solving these involves some more advanced concepts we haven't covered yet. But if you're feeling especially ambitious, you can keep reading.
The backend in branch complete
works pretty much fine, but there is a case where if you and your friends are spamming cat happiness fast enough, some of your clicks may not seem to go through. (e.g. after clicking 1000 times, cat happiness is only 973).
This occurs due to a race condition in the way we handle /api/cat-happiness
.
User.findById(req.body.userId).then((user) => {
user.cat_happiness++;
user.save();
});
Suppose two requests for /api/cat-happiness
execute at nearly the exact same time. Both will run the first line, and ask for the user document. Mongoose gives both processes the following response:
{
_id: "123abc456def",
name: "meme man",
googleid: 987654,
cat_happiness: 0,
}
Then, both procceses run lines 2. Now, for each of them, user
looks like this:
{
_id: "123abc456def",
name: "meme man",
googleid: 987654,
cat_happiness: 1,
}
Do you see the problem? When this gets saved into the database, cat_happiness === 1
, even though there were two requests that came in. One click got lost! How might we solve this? (we may get to this in Advanced MongoDB next week)
You might experience a bug with the Profile button in the navbar. If you go to someone else's profile, and then click on the "Profile" button, you'll notice that nothing on the page changes, even though the URL changes.
Can you figure out why this might be happening? (we may get to this in Advanced React lecture next week)