Skip to content

Commit 6964fdb

Browse files
authored
Merge pull request #13 from ReCoded-Org/m3-fix
Module 3 fixes
2 parents 480c6d2 + 8427b74 commit 6964fdb

File tree

18 files changed

+327
-233
lines changed

18 files changed

+327
-233
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# SQL Queries Practice
22

3-
Assignment Repo Link to be inserted
3+
[Assignment repo link](https://github.com/ReCoded-Org/curriculum-backend-sql-queries-practice)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# MongoDB Queries Practice
22

3-
Assignment repo link to be inserted
3+
[Assignment repo link](https://github.com/ReCoded-Org/curriculum-backend-mongodb-queries-practice)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Sequelize Practice
22

3-
Assignment repo link to be inserted
3+
[Assignment repo link](https://github.com/ReCoded-Org/curriculum-backend-sequelize-practice)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Elasticsearch practice
22

3-
Assignment repo link to be inserted
3+
[Assignment repo link](https://github.com/ReCoded-Org/curriculum-backend-elasticsearch-practice)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,33 @@
11
# Module 3: CRUD and Data Models
2+
3+
Last revised: 09/11/2021
4+
5+
## Summary
6+
A high proportion of applications can be distilled into four simple operations: Create,
7+
Read, Update, and Delete. Students learn to connect their Express.js server to a
8+
MongoDB database using Mongoose.js and implement models and controllers to
9+
perform CRUD operations.
10+
11+
## Outline
12+
13+
- 1 [Schema and CRUD [R]](../module3-crud-and-data-models/r1-schema-and-crud/README.md)
14+
15+
- 1.1 [Model View Controller (MVC) [R]](../module3-crud-and-data-models/r1.1-model-view-controller/README.md)
16+
17+
- 1.2 [Principles of setting up your schema [R]](../module3-crud-and-data-models/r1.2-principles-of-setting-up-your-schema/README.md)
18+
19+
- 1.3 [Setup project schema using MongoDB [L]](../module3-crud-and-data-models/r1.3-setup-project-schema/README.md)
20+
21+
- 1.4 [Setup project schema using Mongoose [L]](../module3-crud-and-data-models/r1.4-setup-project-schema-using-mongoose/README.md)
22+
23+
- 1.5 [Setup project schema using Mongoose with embedding [L]](../module3-crud-and-data-models/r1.5-setup-project-schema-using-mongoose-embedding/README.md)
24+
25+
- 2 [Models and Controllers in Mongoose [R]](../module3-crud-and-data-models/r2-models-and-controllers-in-mongoose/README.md)
26+
27+
- 2.1 [CRUD with Mongoose [L]](../module3-crud-and-data-models/r2.1-crud-with-mongoose/README.md)
28+
29+
- 3 [Custom model methods [R]](../module3-crud-and-data-models/r3-building-custom-methods-on-mongoose/README.md)
30+
31+
- 3.1 [Building custom methods [L]](../module3-crud-and-data-models/r3.1-building-custom-methods/README.md)
32+
33+
- 4 [Summary](../module3-crud-and-data-models/r4-summary/README.md)
Lines changed: 46 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
# Introduction To Database Schemas
1+
# Schema and CRUD
2+
We have learned how to store and query data in different types of databases. In order to connect our database operations with our API code, we need to put together a database schema. The objectives of this lesson are:
3+
1. Getting familiar with database schemas using an ORM/ODM
4+
2. Getting familiar with CRUD operations in our APIs
25

3-
A database schema is a blueprint or architecture of how our data will look. It doesn't hold data itself, but instead describes the shape and structure of the data and how it might be related to other data.
4-
5-
For example, this is a `customer` schema in MongoDB using Mongoose.
6+
## Introduction To Database Schemas
7+
A database schema is a blueprint or architecture of how our data will look. It doesn't hold any data itself, but instead describes the shape and structure of the data and how it might be related to other data.
68

9+
For example, this is a `customer` schema in MongoDB using [Mongoose](https://mongoosejs.com/).
710
```js
811
const mongoose = require("mongoose");
912

@@ -41,21 +44,23 @@ module.exports = (sequelize, DataTypes) => {
4144

4245
We can see that the schema definition for the `customer` has a `name` that is type `string` and a `zipcode` that is of type `number`. The `name` field is mandatory and cannot be empty.
4346

44-
Another concept that can be confused with the database schema is the "Model".
45-
Models are fancy constructors compiled from schema definitions. An instance of a model is called a document. Models are responsible for creating and reading documents from the underlying MongoDB database.
47+
### Models
48+
Sometimes the term "schema" and "model" can be confused with each other. Take a look at [this Stackoverflow discussion](https://stackoverflow.com/questions/25093452/difference-between-data-model-and-database-schema-in-dbms) about the difference between the two.
49+
Our favorite description is this one - "The database schema is one that contains list of attributes and instructions to tell the database engine how data is organised whereas Data model is a collection of conceptional tools for describing data, data-relationship and consistency constraints."
4650

47-
## Introduction to CRUD operations
51+
Take a look again at the Mongoose example from above. You can see that first we define a schema using the `mongoose.Schema()` function and then we define a model using `mongoose.model()` function which takes the schema as a parameter. From this we can tell that the schema is only a representation of the data structure, however it is the model which makes use of this structure to perform the actual operations on the database because it has all the necessary underlying tools for this. We will look at this in practice in some of the next examples.
4852

53+
From the [Mongoose documentation](https://mongoosejs.com/docs/models.html) - "Models are fancy constructors compiled from schema definitions. An instance of a model is called a document. Models are responsible for creating and reading documents from the underlying MongoDB database."
54+
55+
## Introduction to CRUD operations
4956
When we are building APIs, we want our models to provide four basic types of functionality. The model must be able to Create, Read, Update, and Delete resources. Computer scientists often refer to these functions by the acronym CRUD. A model should have the ability to perform at most these four functions in order to be complete.
5057

5158
### CRUD in REST
52-
53-
In a REST environment, CRUD often corresponds to the [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) `POST`, `GET`, `PUT`, and `DELETE`, respectively. These are the fundamental elements of a persistent storage system.
59+
We already know that in a REST environment, CRUD often corresponds to the [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) `POST`, `GET`, `PUT`, and `DELETE`, respectively. These are the fundamental elements of a persistent storage system.
5460

5561
For example, imagine we are working with a system that is keeping track of meals and their corresponding prices for a restaurant. Let's look at how we would implement CRUD operations.
5662

5763
First of all, we need to define our food item schema (we will use mongoose for that), and let's call it "dish".
58-
5964
```js
6065
const mongoose = require("mongoose");
6166

@@ -69,66 +74,52 @@ const dish = new mongoose.Schema({
6974
required: true,
7075
},
7176
tags: [String],
77+
price: Number
7278
});
7379

7480
module.exports = mongoose.model("dish", dish);
7581
```
7682

7783
#### Create
84+
To create resources in a REST environment, we most commonly use the HTTP POST method. POST creates a new resource of the specified resource type. Imagine that we are adding a new food item to the stored list of dishes for this restaurant, and the dish objects are stored in a dishes resource.
7885

79-
To create resources in a REST environment, we most commonly use the HTTP POST method. POST creates a new resource of the specified resource type.
80-
Imagine that we are adding a new food item to the stored list of dishes for this restaurant, and the dish objects are stored in a dishes resource.
81-
82-
Note: Use `POST` when you want to add a child resource under resources collection.
83-
84-
Request:
86+
Note: Use `POST` when you want to add a child resource under resources collection.)
8587

88+
**Request**:
8689
`POST http://www.myrestaurant.com/api/dishes/`
87-
88-
We will need to send the dish data too as an object in the body.
89-
90-
For example
91-
90+
We will need to send the dish data too as an object in the body. For example:
9291
```js
9392
{
9493
title: "Lasagna",
9594
image: "www.food.com/lasagna.jpg",
96-
tags: ["simple", "classic"]
95+
tags: ["simple", "classic"],
96+
price: 10
9797
}
98-
9998
```
100-
101-
On the backend side, our express route will be
102-
99+
**Code**:
103100
```js
104101
router.post("/dishes", async (req, res) => {
105102
// get the data we sent in the body
106103
const dishData = req.body;
107104
try {
108105
// using the create() method with Mongoose will insert the data we sent in the body to our MongoDB database
109-
// and return an object of that data when done
110106
const newDish = await DishModel.create(dishData);
111-
// then, we return the new created dish object
107+
// and return the newly created data when done
112108
res.status(201).json(newDish);
113109
} catch (err) {
114110
res.status(422).json({ message: err.message });
115111
}
116112
});
117-
})
118113
```
119114

120115
#### Read
121-
122116
To read resources in a REST environment, we use the GET method. In practice, reading a resource shouldn't change any information - it should only retrieve it.
123117

124-
To read resources in a REST environment, we use the GET method. Reading a resource should never change any information - it should only retrieve it. REST itself is more like a set of guidelines. Technically, you can change data in a `GET` request, but since we are creating a RESTful API, you shouldn't do that. Having a GET request that updates data in your database would be confusing to the users of your API and violate the expected behavior of REST.
125-
126-
Request:
118+
Note: Technically, you can change data in a `GET` request, but since you are creating a RESTful API, you shouldn't do that and follow the REST guidelines. Having a GET request that updates data in your database would be confusing to the users of your API and violate the expected behavior of REST.
127119

120+
**Request**:
128121
`GET http://www.myrestaurant.com/api/dishes/`
129-
130-
The express route for getting all dished will be
131-
122+
**Code**:
132123
```js
133124
router.get("/dishes", async (_, res) => {
134125
// here, we are using the find() to return all dishes from our MongoDB database
@@ -139,48 +130,40 @@ router.get("/dishes", async (_, res) => {
139130
```
140131

141132
#### Update
142-
143133
PUT is the HTTP method used for the CRUD operation, Update.
144-
So if the price of Avocado Toast has gone up, we should go into the database and update that information using PUT.
145134

146-
Note: Use `PUT` when you want to modify a singular resource which is already a part of resources collection. `PUT` replaces the resource with the data you send in its entirety.
135+
Note: Use `PUT` when you want to modify a singular resource which is already a part of resources collection. `PUT` replaces the resource with the data you send.
147136

148-
Request:
137+
So if the price of Avocado Toast has gone up, we should go into the database and update that information using PUT.
149138

139+
**Request**:
150140
`PUT http://www.myrestaurant.com/dishes/:id`
151-
152-
We will need to send the new dish data too as an object.
153-
154-
For example
155-
141+
We will need to send the new dish data too as an object. For example:
156142
```js
157143
{
158-
title: "New dish title",
144+
title: "Avocado Toast",
159145
image: "www.food.com/dish.jpg",
160-
tags: ["simple", "classic"]
146+
tags: ["simple", "breakfast"],
147+
price: 100
161148
}
162149
```
163150

164-
Note that when using Mongoose you don't have to send all the object fields, you can only send the ones that got changed.
165-
166-
For example, we can only send the title.
167-
151+
Note that when using Mongoose you don't have to send all the object fields, you can only send the ones that got changed. For example, we can only send the title:
168152
```js
169153
{
170-
title: "New dish title",
154+
price: "100"
171155
}
172156
```
173157

174-
Respectively, our express route for both these examples will be
175-
158+
**Code**:
176159
```js
177160
router.put("/dishes/:id", async (req, res) => {
178-
// we need the dish id in order to tell Mongoose which dish to update in our database
161+
// we need the dish id in order to tell mongoose which dish to update in our database
179162
const { id } = req.params;
180163
try {
181-
// the findByIdAndUpdate() will make sure the dish exist before updating it
164+
// the findByIdAndUpdate() will make sure the dish exists before updating it
165+
// the { new: true } here is just to tell mongoose we want the newly updated dish back after the update is complete
182166
const updatedDish = await DishModel.findByIdAndUpdate(id, req.body, {
183-
// the { new: true } here is just to tell Mongoose we want the newely updated dish back
184167
new: true,
185168
});
186169
// we return the updated dish as a JSON object to the user
@@ -192,21 +175,19 @@ router.put("/dishes/:id", async (req, res) => {
192175
```
193176

194177
#### Delete
195-
196178
The CRUD operation Delete corresponds to the HTTP method DELETE. It is used to remove a resource from the system.
197-
Let's say that the world avocado shortage has reached a critical point, and we can no longer afford to serve this modern delicacy at all. We should go into the database and delete the item that corresponds to **Avocado Toast**, which we know has an `id` of 1223.
198179

199-
Request:
180+
Let's say that the world Avocado shortage has reached a critical point, and we can no longer afford to serve this modern delicacy at all. We should go into the database and delete the item that corresponds to *Avocado Toast*, which let's say we know has an `id` of 1223.
200181

182+
**Request**:
201183
`DELETE http://www.myrestaurant.com/dishes/:id`
202184

203-
The express route for this deleting request can be
204-
185+
**Code**:
205186
```js
206187
router.delete("/dishes/:id", async (req, res) => {
207188
const { id } = req.params;
208189
try {
209-
const dish = await PostModel.findByIdAndDelete(id);
190+
const dish = await DishModel.findByIdAndDelete(id);
210191
// the status code is 204 because we are not returning data or entities
211192
return res.status(204).json({ success: true });
212193
} catch (err) {
@@ -215,10 +196,10 @@ router.delete("/dishes/:id", async (req, res) => {
215196
});
216197
```
217198

218-
---
199+
In the next lesson we will look at using schemas and models in our projects.
219200

201+
---
220202
## References
221-
222203
- https://restfulapi.net/
223204
- https://www.educative.io/blog/crud-operations#what
224205
- https://www.educative.io/blog/what-are-database-schemas-examples#types
Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
11
# Model View Controller (MVC)
2+
One of the most popular software design patterns used for web development is the MVC pattern. The objectives of this lesson are:
3+
1. Getting familiar with the MVC pattern
4+
2. Understanding the use of models, views and controllers
25

36
## Introduction to MVC projects
4-
57
When beginning a new project (especially, when using Express), there are several different methods that can be used to set up the overall file structure and flow. One of the most commonly used architectural patterns is called MVC. This acronym stands for "Model, View, Controller".
6-
This pattern is favored because of its alignment with the computer science design principle, [**separation of concerns**](https://en.wikipedia.org/wiki/Separation_of_concerns). By dividing up responsibilities within our file structure, for example, we can have our db connection work in one file and api routes in another file, ...etc.
78

9+
This pattern is favored because of its alignment with the computer science design principle, [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns). We can divide up functional responsibilities within our file structure and separate business logic from display handling. For example, we can have our database connection in one file and API routes in another file.
10+
11+
A common MVC project structure would look something like this:
812
```
913
app-name-here
1014
|- controllers
1115
|- db
1216
|- models
1317
|- node_modules
18+
|- views
1419
.gitignore
1520
index.js
1621
package.json
1722
package-lock.json
1823
```
1924

2025
### Components Of MVC
21-
22-
**Model:** This consists of the structure of our data and handle the database.
23-
24-
**View:** The part of our application which is shown to the user.
25-
26-
**Controller:** Controller has all the logic to control and respond to the action, the user performs using the views.
26+
1. **Model:** As we've read in the previous lesson, this consists of the structure of our data and handles operations to be performed on the database.
27+
2. **View:** The part of our application which handles everything to be shown to the user.
28+
3. **Controller:** This has all the logic to control and respond to the requests which the user is sending by interacting with the views. The controller routes commands to the model and view parts.
2729

2830
### Models
31+
In your `models` folder, you can write the functionality & logic related to the database (if you aren't using an ORM) like insert, fetch, update and delete queries. It takes the query request from the controller & sends the result of the database operation back to the controller. The general naming convention for the model files is: `name-here-model.js`.
2932

30-
In this folder, you can write the functionality & logics related to the database (if you aren't using ORM) like insert, fetch, update, delete queries. It takes the query request from the controller & sends the response back to the controller.
31-
The naming convention for the model files is: `name-here-model.js`.
32-
33-
Here's an example model using JavaScript and Mongoose.
34-
33+
Here's an example model using Mongoose.
3534
```js
3635
// post-model.js
3736

@@ -59,18 +58,19 @@ module.exports = mongoose.model("Post", post);
5958
```
6059

6160
### Views
61+
In your `views` folder, you can write HTML code for displaying a web page on the web browser. You can send the data from the controller to view for displaying data dynamically.
62+
63+
You have already seen this in practice in Module 1 where you stored EJS templates in a folder called `views`. You even assigned this folder as the views folder to Express, by executing:
64+
```js
65+
app.set("views", "views")
66+
```
6267

63-
In this folder, you can write HTML code for displaying a web page on the web browser. You can send the data from the controller to view for displaying data dynamically.
64-
In a back-end application, views are usually not implemented and rather we create a front-end app using maybe `React` to call our `api` end-points to manipulate and dispaly the data in the back-end.
68+
In a backend application, views are usually not implemented and rather we create a frontend application using maybe React to call our backend API endpoints for data fetch and manipulation requests.
6569

6670
### Controllers
67-
68-
Controllers are the layer between the Model and the View. the views can use the controllers to `add`, `read`, `delete`, ...etc data.
69-
In controllers, you can write the functionality & logic to develop dynamic web applications. It takes the data request from the views & sends it to the model and sends the response back to the views.
70-
The naming convention for the model files is: `name-here-controller.js`.
71+
In your `controllers` folder, you can write the functionality & logic to develop dynamic web applications by handling requests and sending responses. It takes the data request from the views & sends it to the model. After receiving the result from the model, it then sends the response back to the views. If there are no views implemented, then it receives and responds to requests from one or more clients. The naming convention for the controller files is: `name-here-controller.js`.
7172

7273
Here is an example:
73-
7474
```js
7575
// post-controller.js
7676

@@ -79,18 +79,20 @@ const router = express.Router();
7979
const Post = require('../models/post-model.js')
8080

8181
router.get('/posts', (req, res) => {
82-
Post.find({})
83-
.then((posts) => {
84-
res.json(posts);
85-
})
86-
.catch(console.error)
87-
})
82+
Post.find({})
83+
.then((posts) => {
84+
res.json(posts);
85+
})
86+
.catch(console.error)
87+
})
8888
});
8989
```
9090

91-
---
91+
You can read more about the MVC pattern in the MDN Web Docs [here](https://developer.mozilla.org/en-US/docs/Glossary/MVC). You can also read on examples of setting up MVC projects in Node.js [here](https://www.sitepoint.com/node-js-mvc-application/) and [here](https://medium.com/@ipenywis/what-is-the-mvc-creating-a-node-js-express-mvc-application-da10625a4eda).
9292

93-
## References
93+
So far we had been implementing most of our logic within a single JS file in previous assignments. Going forward as we learn to build more full-fledged backend applications, we will be following the MVC pattern in our project files structure.
9494

95+
---
96+
## References
9597
- https://medium.com/geekculture/mvc-architecture-with-express-server-e35aedfe7889
9698
- https://codingstatus.com/express-mvc-structure/

0 commit comments

Comments
 (0)