1
00:00:02,130 --> 00:00:03,390
So let's now make sure

2
00:00:03,390 --> 00:00:05,190
that in createNewProduct,

3
00:00:05,190 --> 00:00:07,660
we don't just log the submitted data,

4
00:00:07,660 --> 00:00:10,350
but we actually store it in a database.

5
00:00:10,350 --> 00:00:13,250
And since we use the MVC pattern,

6
00:00:13,250 --> 00:00:17,960
of course, that database access and storage code

7
00:00:17,960 --> 00:00:20,030
should go into a dedicated model

8
00:00:20,030 --> 00:00:24,160
that models our product data and its behavior.

9
00:00:24,160 --> 00:00:27,550
And hence, the models folder is the right place to go.

10
00:00:27,550 --> 00:00:31,890
And in there, I'll add a product.model.js file.

11
00:00:31,890 --> 00:00:33,570
We have the user model already

12
00:00:33,570 --> 00:00:35,590
with all the user related logic.

13
00:00:35,590 --> 00:00:39,093
Now we'll add a new model for the product related logic.

14
00:00:40,140 --> 00:00:41,610
Now for the product model,

15
00:00:41,610 --> 00:00:43,660
I'll start by defining a class

16
00:00:43,660 --> 00:00:45,860
because just as before I wanted to find

17
00:00:45,860 --> 00:00:48,460
a blueprint for all the product objects,

18
00:00:48,460 --> 00:00:52,540
with which I will work later in my controller actions.

19
00:00:52,540 --> 00:00:57,110
And there we can use this constructor method

20
00:00:57,110 --> 00:00:59,920
to define which kind of data we wanna store,

21
00:00:59,920 --> 00:01:02,870
where, when a product is created

22
00:01:02,870 --> 00:01:05,330
before we then add other methods

23
00:01:05,330 --> 00:01:08,480
that allow us to interact with that model.

24
00:01:08,480 --> 00:01:09,370
Last but not least,

25
00:01:09,370 --> 00:01:12,000
we don't just wanna have the model in this file,

26
00:01:12,000 --> 00:01:14,100
but we wanna use it in other files,

27
00:01:14,100 --> 00:01:16,563
so we should export it like this.

28
00:01:17,960 --> 00:01:19,753
But now let's work on the model.

29
00:01:21,320 --> 00:01:25,570
If we have a look at our form for adding a new product,

30
00:01:25,570 --> 00:01:28,850
we see that a product has a title, a image,

31
00:01:28,850 --> 00:01:31,240
the summary field, the price field,

32
00:01:31,240 --> 00:01:33,740
and the description field.

33
00:01:33,740 --> 00:01:35,440
And therefore it would makes sense

34
00:01:35,440 --> 00:01:39,580
to accept these kinds of data here in the constructor.

35
00:01:39,580 --> 00:01:42,390
Now we could accept multiple parameter values

36
00:01:42,390 --> 00:01:46,750
like title, summary, price, and so on,

37
00:01:46,750 --> 00:01:49,970
but here I'll choose an alternative approach

38
00:01:49,970 --> 00:01:53,900
and just accept one parameter, the productData,

39
00:01:53,900 --> 00:01:56,160
which I expect to be an object

40
00:01:56,160 --> 00:02:00,113
that groups all the individual fields that I want together.

41
00:02:00,960 --> 00:02:04,250
And then in the constructor, just as before with the user,

42
00:02:04,250 --> 00:02:06,770
I, of course, do wanna store that data

43
00:02:06,770 --> 00:02:09,410
that we get as a parameter value here

44
00:02:09,410 --> 00:02:12,290
in that to be created product object

45
00:02:12,290 --> 00:02:14,683
for which this class is the blueprint.

46
00:02:15,550 --> 00:02:17,640
We can do that with the help of the this keyword,

47
00:02:17,640 --> 00:02:18,620
as you learned.

48
00:02:18,620 --> 00:02:21,150
And for example, add a title property

49
00:02:21,150 --> 00:02:26,013
to the to be created object where I store productData.title.

50
00:02:26,970 --> 00:02:30,320
And here I will simply use the name

51
00:02:30,320 --> 00:02:35,320
that I also used in my new-product.ejs file,

52
00:02:35,460 --> 00:02:39,300
so in admin, new-product.ejs.

53
00:02:39,300 --> 00:02:43,180
This name, I'll use these names that are defined here

54
00:02:43,180 --> 00:02:46,160
so that I don't accidentally use the wrong name

55
00:02:46,160 --> 00:02:48,390
in some part of my website later,

56
00:02:48,390 --> 00:02:50,650
but that I have a consistent pattern

57
00:02:50,650 --> 00:02:52,430
of accessing the different names

58
00:02:52,430 --> 00:02:54,843
for these different input values.

59
00:02:56,320 --> 00:02:57,870
So that's the title,

60
00:02:57,870 --> 00:02:59,830
then, of course, I wanna store the summary,

61
00:02:59,830 --> 00:03:03,670
which I expect to get on productData.summary

62
00:03:03,670 --> 00:03:08,430
and the price, which should be productData.price

63
00:03:08,430 --> 00:03:10,580
and also the description,

64
00:03:10,580 --> 00:03:15,580
which not surprisingly is found on productData.description,

65
00:03:16,540 --> 00:03:18,290
and then also the image.

66
00:03:18,290 --> 00:03:22,600
Now for this, I wanna access productData.image.

67
00:03:22,600 --> 00:03:27,500
And what I expect to get here is the name of the image file.

68
00:03:27,500 --> 00:03:29,223
That's the thing I want here.

69
00:03:30,340 --> 00:03:35,080
I also want to add another field, the imagePath,

70
00:03:35,080 --> 00:03:37,610
which is the full path to the image,

71
00:03:37,610 --> 00:03:39,913
as it's stored on the server-side.

72
00:03:41,170 --> 00:03:44,800
And for this, I'll create a string with backticks here

73
00:03:44,800 --> 00:03:47,740
so that I can easily inject a dynamic value

74
00:03:47,740 --> 00:03:49,210
into that string.

75
00:03:49,210 --> 00:03:54,210
And the path here will be product-data/images/

76
00:03:56,670 --> 00:03:59,520
and then with dollar sign, curly braces,

77
00:03:59,520 --> 00:04:01,820
I'll inject a value into that string

78
00:04:01,820 --> 00:04:06,473
and that is this.image or productData.image,

79
00:04:08,500 --> 00:04:09,743
so the image name.

80
00:04:11,510 --> 00:04:14,100
With that, I store the image name stand-alone

81
00:04:14,100 --> 00:04:16,529
in case we would need that name somewhere.

82
00:04:16,529 --> 00:04:19,130
And I store the path or I create the path

83
00:04:19,130 --> 00:04:22,530
like this dynamically based on the image name,

84
00:04:22,530 --> 00:04:26,070
since I know in which folder images will be stored here.

85
00:04:26,070 --> 00:04:28,830
If you chose a different folder for storing images,

86
00:04:28,830 --> 00:04:30,633
you, of course, have to adjust this.

87
00:04:31,970 --> 00:04:35,490
I also will add another field, the imageUrl,

88
00:04:35,490 --> 00:04:39,960
which should be the URL which is used on the front-end,

89
00:04:39,960 --> 00:04:44,250
so instead of the HTML code for requesting that image.

90
00:04:44,250 --> 00:04:46,710
And we haven't yet added any logic

91
00:04:46,710 --> 00:04:51,470
for serving those uploaded images, but we will do that soon.

92
00:04:51,470 --> 00:04:54,080
Here, I will then also construct a string

93
00:04:54,080 --> 00:04:58,330
with backticks so that I can inject something into it.

94
00:04:58,330 --> 00:05:01,040
And here, the path which should be used

95
00:05:01,040 --> 00:05:04,040
for requesting the image from my server

96
00:05:04,040 --> 00:05:09,040
could be /products/assets/images/

97
00:05:10,430 --> 00:05:12,073
and then the name of the image.

98
00:05:12,940 --> 00:05:15,630
Now it's up to you which path you define here,

99
00:05:15,630 --> 00:05:18,650
because you will be the person, the developer,

100
00:05:18,650 --> 00:05:20,680
who has to write the back-end code

101
00:05:20,680 --> 00:05:23,170
for then finding the appropriate image

102
00:05:23,170 --> 00:05:25,920
when a request is coming into the server,

103
00:05:25,920 --> 00:05:27,710
targeting this path.

104
00:05:27,710 --> 00:05:31,570
And we'll write this logic together in a couple of minutes.

105
00:05:31,570 --> 00:05:34,090
And now with that, I'm storing all the productData

106
00:05:34,090 --> 00:05:38,050
that I need to store in this product class

107
00:05:38,050 --> 00:05:39,540
or in this product objects

108
00:05:39,540 --> 00:05:42,060
that will be created based on that class

109
00:05:42,060 --> 00:05:44,223
with help of this constructor method.

110
00:05:45,500 --> 00:05:48,230
Now, of course, we will create product objects

111
00:05:48,230 --> 00:05:51,390
with that class so that we can then also interact

112
00:05:51,390 --> 00:05:55,530
with the database and save that data to the database.

113
00:05:55,530 --> 00:05:58,215
And hence, I'll add another method here.

114
00:05:58,215 --> 00:06:01,090
Let's say a save method, the name is up to you though,

115
00:06:01,090 --> 00:06:04,980
which will have the job of talking to the database.

116
00:06:04,980 --> 00:06:07,490
Therefore, I'll turn it into a async method,

117
00:06:07,490 --> 00:06:10,020
because I wanna use the await keyword in there

118
00:06:10,020 --> 00:06:12,800
since we'll be dealing with promises in there.

119
00:06:12,800 --> 00:06:17,800
And I will also import my db object from data, database,

120
00:06:19,760 --> 00:06:22,283
which allows me to interact with the database.

121
00:06:23,410 --> 00:06:24,850
Now here in the save method,

122
00:06:24,850 --> 00:06:28,810
we can then use this db object

123
00:06:28,810 --> 00:06:33,810
by using db.getDb and then calling collection

124
00:06:34,210 --> 00:06:37,010
and accessing the product's collection,

125
00:06:37,010 --> 00:06:40,520
and then calling insertOne on that collection

126
00:06:40,520 --> 00:06:42,363
to insert one new document.

127
00:06:43,350 --> 00:06:48,320
Now, I wanna prepare that document, the productDocument,

128
00:06:48,320 --> 00:06:50,673
if you wanna call it like this or productData.

129
00:06:51,598 --> 00:06:53,020
And that will be a little helper object

130
00:06:53,020 --> 00:06:56,920
which I create on the fly with this object literal notation,

131
00:06:56,920 --> 00:06:59,840
as it's called, by just using these curly braces,

132
00:06:59,840 --> 00:07:02,970
not based on any specific class.

133
00:07:02,970 --> 00:07:05,420
And there, I wanna store the title of the product

134
00:07:05,420 --> 00:07:07,550
and I'll use this.title here.

135
00:07:07,550 --> 00:07:10,000
So the title stored in the title property

136
00:07:10,000 --> 00:07:14,040
of this product object in which this method is placed,

137
00:07:14,040 --> 00:07:17,140
that's the value that will be stored in this title property

138
00:07:17,140 --> 00:07:18,513
of this helper object.

139
00:07:19,910 --> 00:07:23,770
And then I'll add summary with this.summary,

140
00:07:23,770 --> 00:07:27,060
price with this.summary,

141
00:07:27,060 --> 00:07:30,920
not this.summary, with this.price,

142
00:07:30,920 --> 00:07:35,350
then the description with this.description,

143
00:07:35,350 --> 00:07:38,970
and also the image with this.image.

144
00:07:38,970 --> 00:07:42,140
And please note that's just the image name.

145
00:07:42,140 --> 00:07:44,890
That's why I'm creating this dedicated helper object,

146
00:07:44,890 --> 00:07:47,030
because I don't wanna store all the data

147
00:07:47,030 --> 00:07:48,793
I set up here in the constructor.

148
00:07:48,793 --> 00:07:52,100
I don't wanna store the imagePath or imageUrl,

149
00:07:52,100 --> 00:07:53,430
because I will always be able

150
00:07:53,430 --> 00:07:56,600
to dynamically reconstruct this in my code.

151
00:07:56,600 --> 00:08:00,200
And if we ever would move the images into a new folder

152
00:08:00,200 --> 00:08:02,710
and we would have stored the full folder path

153
00:08:02,710 --> 00:08:06,060
in the database, we would have to update all the entries

154
00:08:06,060 --> 00:08:09,340
in the database to match the new folder path.

155
00:08:09,340 --> 00:08:13,710
If we just store the image name and we derived a folder path

156
00:08:13,710 --> 00:08:17,720
here dynamically in our code, instead of in the database,

157
00:08:17,720 --> 00:08:20,460
we are more flexible when it comes to changing

158
00:08:20,460 --> 00:08:22,860
our folder structure on the server.

159
00:08:22,860 --> 00:08:25,020
That's why I just wanna store the image name

160
00:08:25,020 --> 00:08:28,100
in the database and not the full path to the image,

161
00:08:28,100 --> 00:08:29,930
though, you could of course do that as well,

162
00:08:29,930 --> 00:08:31,003
if you want it to.

163
00:08:31,980 --> 00:08:34,059
But then it's this productData object,

164
00:08:34,059 --> 00:08:36,130
which I'll pass to insertOne,

165
00:08:36,130 --> 00:08:38,460
and therefore, that's the data that will be used

166
00:08:38,460 --> 00:08:41,053
for creating a new document in the database.

167
00:08:42,320 --> 00:08:46,240
Now insertOne returns a promise, so I will await this

168
00:08:46,240 --> 00:08:49,390
and we could also accept the result

169
00:08:49,390 --> 00:08:51,460
we get there and look into it,

170
00:08:51,460 --> 00:08:53,540
but here I don't really care about it.

171
00:08:53,540 --> 00:08:56,913
And hence, I'm already done after awaiting for this.

172
00:08:58,750 --> 00:09:02,220
Now we can use this model in the admin controller.

173
00:09:02,220 --> 00:09:03,730
Here in createNewProduct,

174
00:09:03,730 --> 00:09:06,423
we can use it to store a new product.

175
00:09:07,450 --> 00:09:10,710
So I'll import the product class here,

176
00:09:10,710 --> 00:09:14,950
first of all, at the top of this file, going up one level,

177
00:09:14,950 --> 00:09:17,963
diving into models, product.model.

178
00:09:19,508 --> 00:09:22,540
And then here in createNewProduct,

179
00:09:22,540 --> 00:09:26,920
we can add a product constant by calling new Product

180
00:09:26,920 --> 00:09:30,023
and to new Product, I then pass an object,

181
00:09:31,180 --> 00:09:34,130
because in that constructor method

182
00:09:34,130 --> 00:09:36,590
we expect to get one parameter value,

183
00:09:36,590 --> 00:09:39,333
which is an object with all these fields here.

184
00:09:40,770 --> 00:09:42,720
And therefore, I'll pass in this object,

185
00:09:42,720 --> 00:09:45,220
which is basically an object

186
00:09:45,220 --> 00:09:47,460
with all my request body fields,

187
00:09:47,460 --> 00:09:49,350
hence I'll use the spread operator

188
00:09:49,350 --> 00:09:53,080
to paste all that data from my request body

189
00:09:53,080 --> 00:09:54,483
into this new object.

190
00:09:55,400 --> 00:09:57,770
And in addition, an image field,

191
00:09:57,770 --> 00:10:01,250
which if you recall is just the file name,

192
00:10:01,250 --> 00:10:04,430
which I can get on req.file.

193
00:10:04,430 --> 00:10:06,900
And then if you look at the log from earlier,

194
00:10:06,900 --> 00:10:09,750
you see that in there, you had the file name field

195
00:10:09,750 --> 00:10:11,933
with that generated file name.

196
00:10:13,150 --> 00:10:14,940
That's what I wanna store here,

197
00:10:14,940 --> 00:10:17,733
so here it's req.file.filename.

198
00:10:18,690 --> 00:10:22,653
And that is then creating such a product for me.

199
00:10:23,770 --> 00:10:26,340
Now it's not getting stored in the database yet.

200
00:10:26,340 --> 00:10:29,423
For this, we have to call product.save instead.

201
00:10:30,530 --> 00:10:34,400
Now save returns a promise because it's an async method

202
00:10:34,400 --> 00:10:36,910
and you learned that all methods or functions

203
00:10:36,910 --> 00:10:40,540
decorated with async will return promises.

204
00:10:40,540 --> 00:10:43,800
And hence, if you wanna await for that before we redirect,

205
00:10:43,800 --> 00:10:46,090
we have to turn this createNewProduct

206
00:10:46,090 --> 00:10:49,140
controller action function into a async function

207
00:10:49,140 --> 00:10:52,153
with async as well, so that we can use await here.

208
00:10:53,550 --> 00:10:54,910
This could also fail,

209
00:10:54,910 --> 00:10:59,280
so we might want to actually wrap try-catch around this

210
00:10:59,280 --> 00:11:02,010
so that we catch any errors that could occur

211
00:11:02,010 --> 00:11:03,823
whilst trying to save this.

212
00:11:04,760 --> 00:11:08,430
And then we can use the third parameter value,

213
00:11:08,430 --> 00:11:11,640
this next function, which we can accept

214
00:11:11,640 --> 00:11:15,133
to call next in the catch block and forward to this error.

215
00:11:15,970 --> 00:11:17,430
And then I wanna return

216
00:11:17,430 --> 00:11:21,060
so that no other code thereafter executes.

217
00:11:21,060 --> 00:11:23,120
This is how we can handle this error.

218
00:11:23,120 --> 00:11:24,980
And you learned, we need to do this

219
00:11:24,980 --> 00:11:28,180
because Express does not catch and handle errors

220
00:11:28,180 --> 00:11:30,943
that are caused by promises on its own.

221
00:11:32,850 --> 00:11:35,950
Now we redirect thereafter if everything worked

222
00:11:35,950 --> 00:11:38,410
and therefore, we should now be able to save

223
00:11:38,410 --> 00:11:41,000
some productData in the database.

224
00:11:41,000 --> 00:11:42,810
Let's give this a try.

225
00:11:42,810 --> 00:11:47,810
Here, I'll again enter a keyboard as a title,

226
00:11:47,910 --> 00:11:51,170
and then choose my keyboard image here.

227
00:11:51,170 --> 00:11:53,770
This is a great keyboard.

228
00:11:53,770 --> 00:11:55,810
Sounds like a fitting summary.

229
00:11:55,810 --> 00:11:57,343
Let's enter a price.

230
00:11:58,180 --> 00:12:00,640
This is a first product

231
00:12:02,460 --> 00:12:07,020
added via the admin interface.

232
00:12:07,020 --> 00:12:10,170
It's a very useful keyboard

233
00:12:10,170 --> 00:12:15,170
which I am using for recording this video.

234
00:12:17,150 --> 00:12:22,150
Let's hit save, it redirects, get no error here.

235
00:12:22,820 --> 00:12:27,130
And if we go back here to the Mongo shell

236
00:12:27,130 --> 00:12:31,960
connected to the database, if I run db.products.find,

237
00:12:31,960 --> 00:12:35,290
we should find our product here, and we do.

238
00:12:35,290 --> 00:12:36,830
It has the auto assigned ID

239
00:12:36,830 --> 00:12:38,723
and then all the data we entered.

240
00:12:39,990 --> 00:12:43,270
Now, you might notice that price is stored as a string.

241
00:12:43,270 --> 00:12:45,400
That's actually not something I want.

242
00:12:45,400 --> 00:12:47,430
I wanna store it as a number,

243
00:12:47,430 --> 00:12:50,180
but other than that, it's looking good.

244
00:12:50,180 --> 00:12:52,250
Now to store it as a number,

245
00:12:52,250 --> 00:12:55,680
what I'll do is in the product model,

246
00:12:55,680 --> 00:12:58,060
I'll ensure that when I get price here,

247
00:12:58,060 --> 00:13:00,600
I actually add a plus in front of it

248
00:13:00,600 --> 00:13:03,363
which forces a conversion to a number.

249
00:13:04,800 --> 00:13:07,260
That's a little trick, and that's all we need to do

250
00:13:07,260 --> 00:13:09,220
with that price will be a number.

251
00:13:09,220 --> 00:13:11,520
And since I use this.price down there,

252
00:13:11,520 --> 00:13:14,683
which then will be a number, it will be stored as a number.

253
00:13:15,880 --> 00:13:18,280
So to quickly see that if I go back

254
00:13:18,280 --> 00:13:21,760
to that form from before, with all the values I entered,

255
00:13:21,760 --> 00:13:24,690
I did that by using the back button in the browser.

256
00:13:24,690 --> 00:13:28,550
And I quickly delete this product here

257
00:13:28,550 --> 00:13:33,550
by using db.products.deleteOne.

258
00:13:33,710 --> 00:13:37,660
And then I just look for the product with that ID.

259
00:13:37,660 --> 00:13:39,490
That's what you learned before in the course,

260
00:13:39,490 --> 00:13:41,700
in the MongoDB course section.

261
00:13:41,700 --> 00:13:45,850
Then with no products being there,

262
00:13:45,850 --> 00:13:47,683
if I now submit that again,

263
00:13:49,210 --> 00:13:51,020
and I now find all products again.

264
00:13:51,020 --> 00:13:52,420
Here is my product again,

265
00:13:52,420 --> 00:13:55,150
but now price is not surrounded by quotes

266
00:13:55,150 --> 00:13:56,853
and therefore it is a number.

267
00:13:58,230 --> 00:14:01,110
So that is how we can add products

268
00:14:01,110 --> 00:14:03,403
and how we can store them in the database.

269
00:14:04,370 --> 00:14:05,590
That is amazing.

270
00:14:05,590 --> 00:14:06,790
Now, as a next step,

271
00:14:06,790 --> 00:14:10,090
we can make sure that here in this administration area,

272
00:14:10,090 --> 00:14:13,850
we also show a list or a grid of products

273
00:14:13,850 --> 00:14:17,113
where we can then also start editing or deleting them.

