You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/3/en/part3c.md
+49-31Lines changed: 49 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -618,6 +618,24 @@ Once we introduce a database into the mix, it is useful to inspect the state per
618
618
619
619
You can find the code for our current application in its entirety in the <i>part3-4</i> branch of [this GitHub repository](https://github.com/fullstack-hy2020/part3-notes-backend/tree/part3-4).
620
620
621
+
### A true full stack developer's oath
622
+
623
+
It is again time for the exercises. The complexity of our app has now taken another step since besides frontend and backend we also have a database.
624
+
There are indeed really many potential sources of error.
625
+
626
+
So we should once more extend our oath:
627
+
628
+
Full stack development is <i> extremely hard</i>, that is why I will use all the possible means to make it easier
629
+
630
+
- I will have my browser developer console open all the time
631
+
- I will use the network tab of the browser dev tools to ensure that frontend and backend are communicating as I expect
632
+
- I will constantly keep an eye on the state of the server to make sure that the data sent there by the frontend is saved there as I expect
633
+
- <i>I will keep an eye on the database: does the backend save data there in the right format</i>
634
+
- I progress with small steps
635
+
- I will write lots of _console.log_ statements to make sure I understand how the code behaves and to help pinpoint problems
636
+
- If my code does not work, I will not write more code. Instead, I start deleting the code until it works or just return to a state when everything was still working
637
+
- When I ask for help in the course Discord channel or elsewhere I formulate my questions properly, see [here](https://fullstackopen.com/en/part0/general_info#how-to-get-help-in-discord) how to ask for help
In both of the "successful" cases of deleting a resource, the backend responds with the status code <i>204 no content</i>. The two different cases are deleting a note that exists, and deleting a note that does not exist in the database. The _result_ callback parameter could be used for checking if a resource was actually deleted, and we could use that information for returning different status codes for the two cases if we deem it necessary. Any exception that occurs is passed onto the error handler.
859
877
860
878
861
-
The toggling of the importance of a note can be easily accomplished with the [findByIdAndUpdate](https://mongoosejs.com/docs/api/model.html#model_Model-findByIdAndUpdate) method.
879
+
Let's implement the functionality to update a single note, allowing the importance of the note to be changed. The note updating is done as follows:
In the code above, we also allow the content of the note to be edited.
902
+
The note to be updated is first fetched from the database using the _findById_ method. If no object is found in the database with the given id, the value of the variable _note_ is _null_, and the query responds with the status code <i>404 Not Found</i>.
885
903
886
-
Notice that the <em>findByIdAndUpdate</em> method receives a regular JavaScript object as its argument, and not a new note object created with the <em>Note</em> constructor function.
904
+
If an object with the given id is found, its _content_ and _important_ fields are updated with the data provided in the request, and the modified note is saved to the database using the _save()_ method. The HTTP request responds by sending the updated note in the response.
887
905
888
-
There is one important detail regarding the use of the <em>findByIdAndUpdate</em> method. By default, the <em>updatedNote</em> parameter of the event handler receives the original document [without the modifications](https://mongoosejs.com/docs/api/model.html#model_Model-findByIdAndUpdate). We added the optional <code>{ new: true }</code> parameter, which will cause our event handler to be called with the new modified document instead of the original.
906
+
One notable point is that the code now has nested promises, meaning that within the outer _.then_ method, another [promise chain](https://javascript.info/promise-chaining) is defined:
889
907
890
-
After testing the backend directly with Postman or the VS Code REST client, we can verify that it seems to work. The frontend also appears to work with the backend using the database.
908
+
```js
909
+
.then(note=> {
910
+
if (!note) {
911
+
returnresponse.status(404).end()
912
+
}
891
913
892
-
You can find the code for our current application in its entirety in the <i>part3-5</i> branch of [this GitHub repository](https://github.com/fullstack-hy2020/part3-notes-backend/tree/part3-5).
914
+
note.content= content
915
+
note.important= important
893
916
894
-
### A true full stack developer's oath
895
-
896
-
It is again time for the exercises. The complexity of our app has now taken another step since besides frontend and backend we also have a database.
897
-
There are indeed really many potential sources of error.
917
+
// highlight-start
918
+
returnnote.save().then((updatedNote) => {
919
+
response.json(updatedNote)
920
+
})
921
+
// highlight-end
922
+
```
898
923
899
-
So we should once more extend our oath:
924
+
Usually, this is not recommended because it can make the code difficult to read. In this case, however, the solution works because it ensures that the _.then_ block following the _save()_ method is only executed if a note with the given id is found in the database and the _save()_ method is called. In the fourth part of the course, we will explore the async/await syntax, which offers an easier and clearer way to handle such situations.
900
925
901
-
Full stack development is <i> extremely hard</i>, that is why I will use all the possible means to make it easier
926
+
After testing the backend directly with Postman or the VS Code REST client, we can verify that it seems to work. The frontend also appears to work with the backend using the database.
902
927
903
-
- I will have my browser developer console open all the time
904
-
- I will use the network tab of the browser dev tools to ensure that frontend and backend are communicating as I expect
905
-
- I will constantly keep an eye on the state of the server to make sure that the data sent there by the frontend is saved there as I expect
906
-
- <i>I will keep an eye on the database: does the backend save data there in the right format</i>
907
-
- I progress with small steps
908
-
- I will write lots of _console.log_ statements to make sure I understand how the code behaves and to help pinpoint problems
909
-
- If my code does not work, I will not write more code. Instead, I start deleting the code until it works or just return to a state when everything was still working
910
-
- When I ask for help in the course Discord channel or elsewhere I formulate my questions properly, see [here](https://fullstackopen.com/en/part0/general_info#how-to-get-help-in-discord) how to ask for help
928
+
You can find the code for our current application in its entirety in the <i>part3-5</i> branch of [this GitHub repository](https://github.com/fullstack-hy2020/part3-notes-backend/tree/part3-5).
We notice that the backend has now a problem: validations are not done when editing a note.
88
-
The [documentation](https://mongoosejs.com/docs/validation.html#update-validators) addresses the issue by explaining that validations are not run by default when <i>findOneAndUpdate</i> and related methods are executed.
89
-
90
-
The fix is easy. Let us also reformulate the route code a bit:
The application should work almost as-is in Fly.io/Render. We do not have to generate a new production build of the frontend since changes thus far were only on our backend.
Vastauksena on molemmissa "onnistuneissa" tapauksissa statuskoodi <i>204 No Content</i> eli jos olio poistettiin tai olioa ei ollut mutta <i>id</i> oli periaatteessa oikea. Takaisinkutsun parametrin _result_ perusteella olisi mahdollisuus haarautua ja palauttaa tilanteissa eri statuskoodi, jos sille on tarvetta. Mahdollinen poikkeus siirretään jälleen virheenkäsittelijälle.
867
867
868
-
Muistiinpanon tärkeyden muuttamisen mahdollistava olemassa olevan muistiinpanon päivitys onnistuu helposti metodilla [findByIdAndUpdate](https://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate):
868
+
Toteutetaan vielä yksittäisen muistiinpanon muokkaustoiminto, jotta muistiinpanon tärkeyden muuttaminen mahdollistuu. Muistiinpanon muokkaus tapahtuu seuraavasti:
Operaatio mahdollistaa myös muistiinpanon sisällön editoinnin.
891
+
Muokattava muistiinpano haetaan ensin tietokannasta metodilla _findById_. Jos kannasta ei löydy oliota annetulla id:llä, muuttujan _note_ arvo on _null_, ja kyselyyn vastataan statuskoodilla <i>404 Not Found</i>.
892
+
893
+
Jos annettua id:tä vastaava olio löytyy, päivitetään sen _content_- ja _important_-kentät pyynnön mukana tulleella datalla ja tallennetaan muokattu muistiinpano tietokantaan metodilla _save()_. HTTP-pyyntöön vastataan lähettämällä vastauksen mukana päivitetty muistiinpano.
892
894
893
-
Huomaa, että metodin <em>findByIdAndUpdate</em> parametrina tulee antaa normaali JavaScript-olio eikä uuden olion luomisessa käytettävä <em>Note</em>-konstruktorifunktiolla luotu olio.
895
+
Eräs huomionarvoinen seikka on se, että koodissa on nyt ns. sisäkkäiset promiset, eli ulomman _.then_-metodin sisällä on määritelty toinen [promise-ketju](https://javascript.info/promise-chaining):
896
+
897
+
```js
898
+
.then(note=> {
899
+
if (!note) {
900
+
returnresponse.status(404).end()
901
+
}
902
+
903
+
note.content= content
904
+
note.important= important
905
+
906
+
// highlight-start
907
+
returnnote.save().then((updatedNote) => {
908
+
response.json(updatedNote)
909
+
})
910
+
// highlight-end
911
+
```
894
912
895
-
Huomioi operaatioon <em>findByIdAndUpdate</em> liittyen, että oletusarvoisesti tapahtumankäsittelijä saa parametrikseen <em>updatedNote</em> päivitetyn olion [ennen muutosta](https://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate) olleen tilan. Lisäsimme operaatioon parametrin <code>{ new: true }</code>, jotta saamme muuttuneen olion palautetuksi kutsujalle.
913
+
Yleensä tällaista ei suositella, koska se voi tehdä koodista vaikealukuista. Tässä tapauksessa ratkaisu kuitenkin toimii, sillä näin voimme varmistua siitä, että _.save()_-metodin jälkeiseen _.then_-lohkoon mennään vain, jos id:tä vastaava muistiinpano on löytynyt kannasta ja _save()_-metodia on kutsuttu. Tutustumme kurssin neljännessä osassa async/await-syntaksiin, joka tarjoaa helpomman ja selkeämmän kirjoitustavan tämänkaltaisiin tilanteisiin.
896
914
897
915
Backend vaikuttaa toimivan Postmanista ja VS Coden REST Clientistä tehtyjen kokeilujen perusteella. Myös frontend toimii moitteettomasti tietokantaa käyttävän backendin kanssa.

86
86
87
-
Huomaamme kuitenkin että sovelluksessa on pieni ongelma, validaatiota ei suoriteta muistiinpanojen päivityksen yhteydessä. [Dokumentaatio](https://mongoosejs.com/docs/validation.html#update-validators) kertoo mistä on kyse, validaatiota ei suoriteta oletusarvoisesti metodin <i>findOneAndUpdate</i> suorituksen yhteydessä.
88
-
89
-
Korjaus on onneksi helppo. Muotoillaan routea muutenkin hieman siistimmäksi:
### Tietokantaa käyttävän version vieminen tuotantoon
108
88
109
89
Sovelluksen pitäisi toimia tuotannossa eli Fly.io:ssa tai Renderissä lähes sellaisenaan. Frontendin muutosten takia on tehtävä siitä uusi tuotantoversio ja kopioitava se backendiin.
0 commit comments