{"id":2010,"date":"2020-03-09T14:13:51","date_gmt":"2020-03-09T14:43:51","guid":{"rendered":"https:\/\/ultering.com\/it4us\/?p=2010"},"modified":"2022-06-24T12:15:34","modified_gmt":"2022-06-24T12:45:34","slug":"node-js-using-sequelize-express-project-multiple-sources-draft","status":"publish","type":"post","link":"https:\/\/ultering.com\/it4us\/?p=2010","title":{"rendered":"NODE.JS: VIEW USING EXPRESS AND SEQUELIZE &#8211; 2ND STEP"},"content":{"rendered":"<p>Revision 2022<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_73 counter-hierarchy ez-toc-counter ez-toc-white ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-69f60a2872759\" class=\"ez-toc-cssicon-toggle-label\"><span class><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\" \/><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\" \/><\/svg><\/span><\/span><\/label><input type=\"checkbox\" id=\"ez-toc-cssicon-toggle-item-69f60a2872759\" checked aria-label=\"Toggle\"><nav><ul class=\"ez-toc-list ez-toc-list-level-1 \"><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#TARGET\" title=\"TARGET\">TARGET<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#FAST_START_FOR_THE_IMPATIENT\" title=\"FAST START FOR THE IMPATIENT\">FAST START FOR THE IMPATIENT<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#GENERAL_NOTES\" title=\"GENERAL NOTES\">GENERAL NOTES<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#REFACTORING_THE_CODE_FROM_1ST_STEP\" title=\"REFACTORING THE CODE FROM 1ST STEP\">REFACTORING THE CODE FROM 1ST STEP<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Refactoring_appjs_file\" title=\"Refactoring app.js file\">Refactoring app.js file<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Creating_Routes\" title=\"Creating Routes\">Creating Routes<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Creating_Users_Route\" title=\"Creating User&#8217;s Route\">Creating User&#8217;s Route<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Creating_the_Users_view\" title=\"Creating the User&#8217;s view\">Creating the User&#8217;s view<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Testing_The_Users_routing\" title=\"Testing The User&#8217;s routing\">Testing The User&#8217;s routing<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#REFACTORING_THE_PERSISTENCE\" title=\"REFACTORING THE PERSISTENCE\">REFACTORING THE PERSISTENCE<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Creating_the_Configuration_Layer\" title=\"Creating the Configuration Layer\">Creating the Configuration Layer<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Create_the_Persistence_Layer\" title=\"Create the Persistence Layer\">Create the Persistence Layer<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Register_the_PgSeqlDB_in_appjs\" title=\"Register the PgSeqlDB in app.js\">Register the PgSeqlDB in app.js<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#How_does_this_code_work\" title=\"How does this code work?\">How does this code work?<\/a><\/li><\/ul><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#REFACTORING_appjs_and_User_Router\" title=\"REFACTORING: app.js and User Router\">REFACTORING: app.js and User Router<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#REFACTORING_THE_VIEW_TO_SHOW_THE_USER_INSTANCES\" title=\"REFACTORING THE VIEW TO SHOW THE USER INSTANCES\">REFACTORING THE VIEW TO SHOW THE USER INSTANCES<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Adding_Bootstrap_and_the_Static_Files\" title=\"Adding Bootstrap and the Static Files\">Adding Bootstrap and the Static Files<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Refactoring_the_userejs_View\" title=\"Refactoring the user.ejs View\">Refactoring the user.ejs View<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#usersejs\" title=\"users.ejs\">users.ejs<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#_REFACTORING_THE_PERSISTENCE_LAYER_ONCE_MORE\" title=\"&nbsp;REFACTORING THE PERSISTENCE LAYER ONCE MORE\">&nbsp;REFACTORING THE PERSISTENCE LAYER ONCE MORE<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#Testing_the_User_List\" title=\"Testing the User List\">Testing the User List<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/ultering.com\/it4us\/?p=2010\/#SOURCE_CODE\" title=\"SOURCE CODE\">SOURCE CODE<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"TARGET\"><\/span>TARGET<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Post revised at 2022.<\/p>\n<div>\n<p><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6967\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg\" alt width=\"1000\" height=\"541\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg 1000w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-300x162.jpg 300w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-768x415.jpg 768w\" sizes=\"(max-width: 1000px) 100vw, 1000px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6967 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%20541%22%3E%3C%2Fsvg%3E\" alt width=\"1000\" height=\"541\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%20541%22%3E%3C%2Fsvg%3E 1000w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg 1000w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-300x162.jpg 300w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-768x415.jpg 768w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg\"><\/p>\n<p><strong><br>\nCREATING THE VIEW LAYER USING STUBS<\/strong><\/p>\n<\/div>\n<p>This step of the project will create a <em>Todo list<\/em> as shown in the picture above, using Bootstrap.<\/p>\n<div>\n<p>This project evolves from the <a href=\"https:\/\/ultering.com\/it4us\/?p=1953\">1st step<\/a>.<\/p>\n<p>Now, let&#8217;s follow to the 2nd step.<\/p>\n<p>Projects need speed, so it goes faster using multiple development threads.<\/p>\n<p>Suppose a small team (most cases in companies).<br>\nThis team is split into front-end developers and back-end developers.<\/p>\n<p>While the backend team is providing the persistence support, it may be offered a stub mocking the persistence to be used by the frontend team that simulates the database in order to show faster results to the stakeholders in order to obtain the approval confirmations at the very beginning of the project.<\/p>\n<p>There are many ways of doing this.<\/p>\n<p>One of the simplest is to create in-line code or hard-coded data.<br>\nA simple JavaScript array will do a good job, but when the complexity comes to a certain degree, such kind of approach doesn&#8217;t fit at all reverting as a disadvantage, remembering that users always ask for more and more. <em>Gosh! Thank you!<\/em>&nbsp; &nbsp;\ud83d\ude42<\/p>\n<p>In this example, applying the concept of a View Helper design pattern, we create an Object-Oriented stub instead of using a mock library to supply simulated dynamic changes in order that offers a more resourceful presentation.<\/p>\n<p>Why not use a mock library?<br>\nMocks use a different approach, separating status verification from behavior verification for Unit Test purposes.<br>\nIn this example there is no need since we are just simulating the database with known data, intrinsically assumed as already validated.<\/p>\n<p>Note:<br>\nA stub definition may have different concepts.<br>\nOne under Unit Test context, the other outside it. Same as mocking.<br>\nHere, we are not testing the application, but just replacing a resource, simulating it \u2014 a mock, but not pertaining to the concept linked to Unit Test context.<br>\nMore information here:<br>\n<a href=\"https:\/\/martinfowler.com\/articles\/mocksArentStubs.html\">martinfowler.com\/articles\/mocksArentStubs.html<\/a><br>\n<a href=\"https:\/\/whatis.techtarget.com\/definition\/stub\">What is stub? &#8211; Definition from WhatIs.com<\/a><br>\n<a href=\"https:\/\/stackoverflow.com\/questions\/3459287\/whats-the-difference-between-a-mock-stub\">stackoverflow dicussion &#8211; many opinions<\/a><\/p>\n<\/div>\n<h2><\/h2>\n<h2><span class=\"ez-toc-section\" id=\"FAST_START_FOR_THE_IMPATIENT\"><\/span>FAST START FOR THE IMPATIENT<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>&#8211; Help for linux (debian\/ubuntu) install:<\/strong><br>\n<a href=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/ultering_sequelize_tutorial_debian_install.txt\">ultering_sequelize_tutorial_debian_install<\/a><\/p>\n<p>After installing check the windows install below.<\/p>\n<p><strong>&#8211; Database user setup (just in the case):<br>\n<a href=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/postgres_user_setup.txt\">postgres_user_setup<\/a><\/strong><\/p>\n<p><strong><br>\n&#8211; Windows install:<br>\n<\/strong><\/p>\n<p>1. Download source code from:<\/p>\n<p><a href=\"https:\/\/github.com\/alsdias\/node_sequelize_ultering_ml40643_2nd_step\">node_sequelize_ultering_ml40643_2nd_step<\/a><\/p>\n<p>2. Use the same node_modules dir created from <a href=\"https:\/\/ultering.com\/it4us\/?p=1953\">1st step<\/a>.<br>\nYou may move it to save time and disk space.<\/p>\n<p>If you don&#8217;t have it, you may create it following this sequence of commands:<\/p>\n<pre class>npm install --save express express-generator\nnpm install - -save nodemon\nnpm install --save sequelize sequelize-cli\nnpm install --save pg pg-hstore\nnpm install --save sequelize sequelize-cli dotenv\nnpm install --save serve-favicon\nnpm audit fix --force\n<\/pre>\n<p>3. Go to app root dir and edit the config.json user config dir.<br>\nSwitch the database configuration for your respective choice (dev\/local, cloud, etc.).<\/p>\n<p>4. Go to the app root dir and edit run.bat.<br>\nSet the APP_ENV envvar to match your choice.<\/p>\n<p>rem SET APP_ENV=dev<br>\nSET APP_ENV=cloud<\/p>\n<p>6. Edit app.js.<br>\nCheck the following lines, that shall be set to false on the first run:<\/p>\n<div>\n<div>createTable = false;<\/div>\n<div>populate = false;<\/div>\n<\/div>\n<p>7. Run the app:<br>\nrun.bat<\/p>\n<p>8. Point to:<br>\nhttp:\/\/localhost:3000\/users<\/p>\n<p>9. Stop the app (Ctrl+C).<\/p>\n<p>10. Switch:<br>\ncreateTable = false;<br>\nto<br>\ncreateTable = true;<\/p>\n<p>Run the app again.<br>\nCheck the database with a db client.<br>\nThe user table was created.<\/p>\n<p>10. Stop the app again.<br>\nIMPORTANT: don&#8217;t switch the <em>booleans<\/em> with the application running.<\/p>\n<p>11. Switch to:<\/p>\n<div>\n<div>createTable = false;<\/div>\n<div>populate = true;<\/div>\n<\/div>\n<div><\/div>\n<div>\n<p>12. Stop the app.<\/p>\n<p>13. Switch to:<br>\npopulate = false<\/p>\n<div>14. Refresh the browser&#8217;s page.<br>\nThe tables was populated.<\/div>\n<\/div>\n<div>\n<div><\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"GENERAL_NOTES\"><\/span><strong>GENERAL NOTES<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>1. The source code doesn&#8217;t include the <em>node_modules<\/em> folder content.<br>\nFollowing the instructions, the <em>node_modules<\/em> content is automatically generated, but if desired it may be copied from the 1st step on <strong><a href=\"https:\/\/github.com\/alsdias\/nodejs-sequelize-tutorials\">GitHub<\/a><\/strong>&nbsp;under <em>rin544b_1st_step folder<\/em>.<\/p>\n<p>2. The tutorial assumes Windows since it is the most used O.S. For Linux or Mac, you may just convert the system&#8217;s commands, but those pertaining to Node.js or npm commands are the same.<\/p>\n<p>3. The $INSTALLDIR is the root dir where you&#8217;re supposed to place your project. For example, $INSTALLDIR=C:nodelab<\/p>\n<p>4. The tutorial assumes that commands are issued on a prompt (console).<\/p>\n<p>5. Although this tutorial uses PostgreSQL, it may be used any other database since the purpose of ORM is to provide a layer of abstraction for the database&#8217;s implementations. In this case, switch the configuration to match your choice, for instance, &#8220;dialect&#8221; property value must be replaced by the new value from your choice.<\/p>\n<p>6.<strong> <em>IMPORTANT<\/em><\/strong>:<br>\n<span style=\"color: #333300;\"><strong>To protect clarity and keep the tutorial concise, the sequence and topics are provided in order to accomplish the main tutorial&#8217;s goal.<\/strong><\/span><br>\n<span style=\"color: #333300;\"><strong>Of course, some details may cause some discomfort to the reader depending on his own knowledge and understanding.<\/strong><\/span><br>\n<span style=\"color: #333300;\"><strong>In such cases, we recommend that doubts may be solved comparing your code with the source code provided at the begin or at the end of this tutorial.<\/strong><\/span><\/p>\n<p>*********************************************************************************************<\/p>\n<p><strong>To start using this tutorial at its 2nd step, better if continuing from the first step:<\/strong><br>\n<strong>Node.js v.16: <a href=\"https:\/\/github.com\/alsdias\/nodejs-sequelize-tutorials\">GitHub<\/a>&nbsp;, rin544b_1st_step<\/strong><\/p>\n<p><strong>Source code after the tutorial is complete: download on <a href=\"https:\/\/github.com\/alsdias\/nodejs-sequelize-tutorials\">GitHub<\/a><\/strong> , rin544c_2nd_step<br>\n*********************************************************************************************<\/p>\n<h2><\/h2>\n<h2><span class=\"ez-toc-section\" id=\"REFACTORING_THE_CODE_FROM_1ST_STEP\"><\/span>REFACTORING THE CODE FROM 1ST STEP<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"Refactoring_appjs_file\"><\/span>Refactoring app.js file<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Cut the code from:<br>\n<em>var pg = require(&#8216;pg&#8217;);<\/em><\/p>\n<p>up to the end but keep the modules.export statement:<br>\nmodule.exports = app;<\/p>\n<p>You may paste the code to a temporary file to help you understand what was done before and comparing it to the new code we are going to implement.<\/p>\n<p>You shall have the app.js file like this:<\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6929\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_01.jpg\" alt width=\"610\" height=\"877\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_01.jpg 610w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_01-209x300.jpg 209w\" sizes=\"(max-width: 610px) 100vw, 610px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6929 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20610%20877%22%3E%3C%2Fsvg%3E\" alt width=\"610\" height=\"877\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20610%20877%22%3E%3C%2Fsvg%3E 610w\" sizes=\"(max-width: 610px) 100vw, 610px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_01.jpg 610w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_01-209x300.jpg 209w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_01.jpg\"><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Creating_Routes\"><\/span>Creating Routes<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>MVC projects have three layers: model, view, and control.<br>\nThe model contains the business cases (from use cases) and the persistence model.<br>\nThe view is responsible for rendering the content returned to the browser.<br>\nThe control layer is responsible to handle the requisitions.<\/p>\n<p>The app.js file in this project contains the code that handles our requisitions, so it plays the role of the front controller.<br>\nAs the application grows, it is also necessary to split the code in order to keep it legible, maintainable.<br>\nThe routes are specialized requisition handlers that enable us to divide the requisitions into groups turning the code easier to maintain the navigation.<\/p>\n<p>&nbsp;<\/p>\n<h4><span class=\"ez-toc-section\" id=\"Creating_Users_Route\"><\/span>Creating User&#8217;s Route<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>The &#8220;express&#8221; in the 1st step has already created part of the code for users.<br>\nYou may find it in app.js file at:<\/p>\n<p><em>app.use(&#8216;\/users&#8217;, usersRouter);<\/em><\/p>\n<p>&nbsp;<\/p>\n<p>All we have to do is to complete the task providing a specific routing service for Users.<\/p>\n<p>cd node<br>\necho. &gt; routes\\users.js<\/p>\n<p>Now edit &#8220;routes\\users.js&#8221; and copy the content from &#8220;routes\\index.js&#8221;, making small changes as shown below:<\/p>\n<pre class>var express = require('express');\nvar router = express.Router();\n\nrouter.get('\/', function(req, res, next) {\n  res.render('users', { title: 'USERS' });\n});\n\nmodule.exports = router;\n\n<\/pre>\n<p>If you have noticed, this code was copied from index.ejs and it was changed just this line:<br>\n<em>&nbsp; res.render(&#8216;users&#8217;, { title: &#8216;USERS&#8217; });<\/em><\/p>\n<div>It is a good starting point.<br>\nStart simpler and evolve at each iteration.\n<div>It remembers the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Iterative_and_incremental_development\">Iterative and incremental<\/a> development method, an excellent approach.<\/div>\n<p>NOTE: the idea of this tutorial is to evoke concepts, principles and patterns but there is no space here to go deeper.<\/p>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"Creating_the_Users_view\"><\/span>Creating the User&#8217;s view<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>echo. &gt; view\\users.ejs<\/p>\n<p>Edit view\\users.ejs and add:<\/p>\n<pre class>&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;&lt;%= title %&gt;&lt;\/title&gt;\n    &lt;link rel='stylesheet' href='\/stylesheets\/style.css' \/&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n    &lt;h1&gt;&lt;%= title %&gt;&lt;\/h1&gt;\n    &lt;p&gt;Welcome to &lt;%= title %&gt;&lt;\/p&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;\n\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Testing_The_Users_routing\"><\/span>Testing The User&#8217;s routing<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Run the app:<br>\nrun.bat<\/p>\n<p>Point to:<br>\nhttp:\/\/localhost:3000\/users<\/p>\n<p>You shall get:<\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6931\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_02.jpg\" alt width=\"420\" height=\"284\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_02.jpg 420w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_02-300x203.jpg 300w\" sizes=\"(max-width: 420px) 100vw, 420px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6931 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20420%20284%22%3E%3C%2Fsvg%3E\" alt width=\"420\" height=\"284\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20420%20284%22%3E%3C%2Fsvg%3E 420w\" sizes=\"(max-width: 420px) 100vw, 420px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_02.jpg 420w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_02-300x203.jpg 300w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_02.jpg\"><\/p>\n<p>One more little step was accomplished.<br>\nNow, we are going to prepare the persistence layer and then we come back to the view to increment the view artifact.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<pre class><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"REFACTORING_THE_PERSISTENCE\"><\/span>REFACTORING THE PERSISTENCE<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The 1st step used the app.js file to implement persistence for the sake of simplicity.<br>\nThis was a didactic approach and shall not be used professionally.<br>\nA better way is to create specific files under their proper layers.<\/p>\n<p>Why?<\/p>\n<p><span data-preserver-spaces=\"true\">It is easier to maintain because if we put everything into just one file makes hard to maintain the code as it grows.<br>\n<\/span><span data-preserver-spaces=\"true\">Even though we use many files, we must consider how to set them together using known patterns.<br>\n<\/span><span data-preserver-spaces=\"true\">Code organization is vital for a well-designed app and shall consider&nbsp;<\/span><a class=\"editor-rtfLink\" href=\"https:\/\/en.wikipedia.org\/wiki\/Separation_of_concerns\" target=\"_blank\" rel=\"noopener\"><span data-preserver-spaces=\"true\">separation of concerns<\/span><\/a><span data-preserver-spaces=\"true\">.<br>\n<\/span><span data-preserver-spaces=\"true\">In this tutorial, we apply small pieces of concepts of many patterns that lead a good app to a successful result.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Creating_the_Configuration_Layer\"><\/span>Creating the Configuration Layer<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The configuration layer may hold the app&#8217;s configurations.<br>\nIn this tutorial, al least at this step, there will be just the database&#8217;s configuration.<\/p>\n<p>cd node<br>\nmkdir config<br>\necho. &gt; config\\config.json<\/p>\n<p>&nbsp;<\/p>\n<p>Add the following code to the config.json file:<\/p>\n<pre class>{\n  \"development\": {\n    \"username\": \"postgres\",\n    \"password\": \"postgres\",\n    \"database\": \"rin544_dev\",\n    \"host\": \"127.0.0.1\",\n    \"dialect\": \"postgres\",\n\t\"port\": \"5432\"\n  },\n  \"db_dev_url\": \"postgres:\/\/postgres:postgres@localhost:5432\/rin544_dev\",\n  \"test\": {\n    \"username\": \"postgres\",\n    \"password\": \"postgres\",\n    \"database\": \"rin544_test\",\n    \"host\": \"127.0.0.1\",\n    \"dialect\": \"postgres\",\n\t\"port\": \"5432\"\n  },\n  \"db_test_url\": \"postgres:\/\/postgres:postgres@localhost:5432\/rin544_test\",\n  \"production\": {\n    \"username\": \"postgres\",\n    \"password\": \"postgres\",\n    \"database\": \"rin544\",\n    \"host\": \"127.0.0.1\",\n    \"dialect\": \"postgres\",\n\t\"port\": \"5432\"\n  },\n  \"db_prod_url\": \"postgres:\/\/postgres:postgres@localhost:5432\/rin544\",\n  \"cloud\": {\n    \"username\": \"mutclyib\",\n    \"password\": \"89RRrgOpCmuNkZxBMPxWC-5Koz2hvYCJ\",\n    \"database\": \"mutclyib\",\n    \"host\": \"tuffi.db.elephantsql.com\",\n    \"dialect\": \"postgres\",\n\t\"port\": \"5432\"\n  },\n  \"db_cloud_url\": \"postgres:\/\/mutclyib:89RRrgOpCmuNkZxBMPxWC-5Koz2hvYCJ@tuffi.db.elephantsql.com:5432\/mutclyib\"\n}\n\n<\/pre>\n<p>As you may notice, the configuration simultes a real case when we have different database configurations for dev, prod, etc.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Create_the_Persistence_Layer\"><\/span>Create the Persistence Layer<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>mkdir models\\persistence<br>\necho. &gt; models\\persistence\\PgSeqlDB.js<\/p>\n<p>This step rewrites the previous persistence implementation written in app.js to its own file.<\/p>\n<p>You may choose to download this file: <a href=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/PgSeqlDB.7z\">PgSeqlDB<\/a>, or copy the code below:<\/p>\n<pre class><\/pre>\n<pre class>var Dbconfig = require('..\/..\/config\/config.json');\nvar Sequelize = require('sequelize');\n\n\/**\n * Database service using Sequelize and PostgreSQL.\n *\n * @class PgSeqlDB\n *\/\nclass PgSeqlDB {\n\n    dbconfig;\n    sequelize;\n    createTables = false;\n    userModel;\n\n    configuration() {\n        \/\/ process.env.APP_ENV captures what was set in the run.bat in the line: SET APP_ENV=dev\n        if (process.env.APP_ENV == 'dev') {\n            console.log('[INFO]: database configuration set to development.')\n            return Dbconfig.development;\n        } else if (process.env.APP_ENV == 'prod') {\n            console.log('[INFO]: database configuration set to production.');\n            return Dbconfig.production;\n        } else if (process.env.APP_ENV == 'cloud') {\n            console.log('[INFO]: database configuration set to cloud.');\n            return Dbconfig.cloud;\n        } else if (process.env.APP_ENV == 'test') {\n            console.log('[INFO]: database configuration set to test environment.')\n            return Dbconfig.test;\n        }\n        console.log('[WARN]: database configuration not defined, assuming default (dev): ' + Dbconfig.development.database);\n        return Dbconfig.development;\n    }\n\n\n    constructor(createTables) {\n        this.createTables = createTables;\n        this.dbconfig = this.configuration();\n        this.sequelize = this.connection();\n        this.defineUserModel();\n        this.syncDb(this.createTables);\n    }\n\n    defineUserModel() {\n        this.userModel = this.sequelize.define('User', {\n            id: {\n                type: Sequelize.INTEGER,\n                allowNull: false,\n                autoIncrement: true,\n                primaryKey: true\n            },\n            username: Sequelize.STRING,\n            password: Sequelize.STRING\n        }, {\n            tableName: 'user', \/\/ this will define the table's name\n            \/\/timestamps: false           \/\/ this will deactivate the timestamp columns\n        });\n\n    }\n\n    connection() {\n        console.log('[INFO]: authenticating database: ' + this.dbconfig.database)\n        let sequelize = new Sequelize({\n            username: this.dbconfig.username,\n            password: this.dbconfig.password,\n            database: this.dbconfig.database,\n            host: this.dbconfig.host,\n            port: this.dbconfig.port,\n            dialect: this.dbconfig.dialect\n        });\n\n        sequelize.authenticate().then(function () {\n            console.log('[INFO]: database authenticated');\n        }, function (err) {\n            console.log('[EXCP]: database authentication failed due to: ' + err)\n        });\n        return sequelize;\n    }\n\n    \/**\n     * @param  {boolean} createTables if true, creates the tables.\n     *\/\n    syncDb(createTables) {\n        this.sequelize.sync({\n                force: createTables\n            })\n            .then(function (err) {\n                \/\/console.log('[INFO]: sequelize sync done');\n            }, function (err) {\n                console.log('An error occurred while creating the table:', err);\n            });\n    }\n\n\n    insertUser(name, pass) {\n        this.userModel.create({\n            username: name,\n            password: pass\n        }).then(function (user) {\n            console.log('[INFO]: ' + user.dataValues.username + ' persisted');\n        });\n    }\n\n    populate() {\n        this.insertUser(\"John Doe\", \"secret1\");\n        this.insertUser(\"Mary Doe\", \"secret2\");\n        this.insertUser(\"Jane Doe\", \"secret3\");\n    }\n\n    showConfig() {\n        console.log(this.dbconfig);\n    }\n\n    findById(id) {\n        this.userModel.findByPk(id).then(function (user) {\n            console.log('------------------------------------------');\n            console.log('\\n[INFO]: found: ' + user.id + \", \" + user.username + '\\n');\n        });\n    }\n\n    findByName(name) {\n        this.userModel.findAll({\n            where: {\n                username: name\n            }\n        }).then(function (data, err) {\n            if (!data) {\n                console.log('------------------------------------------');\n                console.log('[FAIL]: user instance not found due to: ' + err);\n                console.log('------------------------------------------');\n            } else {\n                console.log('------------------------------------------');\n                \/\/console.log(data);\n                for (let u in data) {\n                    console.log(data[u].dataValues);\n                }\n                console.log('------------------------------------------');\n            }\n        })\n    }\n\n    findAll(res) {\n        this.userModel.findAll().then(function (data, err) {\n            if (!data) {\n                console.log('------------------------------------------');\n                console.log('[FAIL]: user instance not found due to: ' + err);\n                console.log('------------------------------------------');\n            } else {\n                let list = [];\n                for (let u of data) {\n                    list.push(u.dataValues);\n                }\n                return res.render('users', {\n                    title: 'USERS',\n                    users: list\n                });\n\n            }\n        })\n    }\n\n};\n\n\nmodule.exports = PgSeqlDB;\n<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Register_the_PgSeqlDB_in_appjs\"><\/span>Register the PgSeqlDB in app.js<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Append the following in the app.js file, always before the module.exports statement.<\/p>\n<p>&nbsp;<\/p>\n<pre class>const PgSeqlDB = require('.\/models\/persistence\/PgSeqlDB');\ncreateTable = true;\npopulate = false;\nlet pgSeqDB = new PgSeqlDB(createTable);\n\/\/ pgSeqDB.showConfig();\nif (!createTable &amp;&amp; populate) {\n  pgSeqDB.populate();\n}\nif(!createTable &amp;&amp; !populate) {\n  pgSeqDB.findById(1);\n  pgSeqDB.findByName('John Doe');\n  pgSeqDB.findAll();\n}\n<\/pre>\n<p>&nbsp;<\/p>\n<p>You shall get the app.js like this:<\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6945\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_06.jpg\" alt width=\"658\" height=\"669\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_06.jpg 658w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_06-295x300.jpg 295w\" sizes=\"(max-width: 658px) 100vw, 658px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6945 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20658%20669%22%3E%3C%2Fsvg%3E\" alt width=\"658\" height=\"669\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20658%20669%22%3E%3C%2Fsvg%3E 658w\" sizes=\"(max-width: 658px) 100vw, 658px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_06.jpg 658w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_06-295x300.jpg 295w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_06.jpg\"><\/p>\n<h4><\/h4>\n<h4><span class=\"ez-toc-section\" id=\"How_does_this_code_work\"><\/span>How does this code work?<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>It follows the same logic used in the 1st step except that you now have the code implemented in its own file.<\/p>\n<p>Follow this procedure:<\/p>\n<ol>\n<li>Creating the tables.<br>\nFollow the picture:<br>\n<strong><em>createTable = true;<\/em><\/strong><br>\n<strong><em>populate = false;<\/em><\/strong><br>\nRun the application (run.bat).<br>\nCheck the database (the user table is created without content).<br>\nThe user table is created on the database:<br>\n.<br>\n<noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6941\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_05.jpg\" alt width=\"393\" height=\"481\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_05.jpg 393w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_05-245x300.jpg 245w\" sizes=\"(max-width: 393px) 100vw, 393px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6941 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20393%20481%22%3E%3C%2Fsvg%3E\" alt width=\"393\" height=\"481\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20393%20481%22%3E%3C%2Fsvg%3E 393w\" sizes=\"(max-width: 393px) 100vw, 393px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_05.jpg 393w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_05-245x300.jpg 245w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_05.jpg\"><br>\n.<\/li>\n<li>Without the need to stop the app switch the flags as follow and save:<br>\n<strong>createTable = false;<\/strong><br>\n<strong>populate = true;<\/strong><br>\nThe user table is populated.<br>\nGo to the console and check the output .<br>\nCheck the database and perform a select:<br>\n<em>&nbsp; &nbsp;select * from public.user;<\/em><br>\n.<br>\n<em><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6947\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_07.jpg\" alt width=\"513\" height=\"98\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_07.jpg 513w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_07-300x57.jpg 300w\" sizes=\"(max-width: 513px) 100vw, 513px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6947 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20513%2098%22%3E%3C%2Fsvg%3E\" alt width=\"513\" height=\"98\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20513%2098%22%3E%3C%2Fsvg%3E 513w\" sizes=\"(max-width: 513px) 100vw, 513px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_07.jpg 513w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_07-300x57.jpg 300w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_07.jpg\"><\/em><br>\n.<em><br>\n<\/em>Also, go to the console and check the output .<br>\n.<\/li>\n<li>Again, without the need to stop the app switch the flags as follow:<br>\n<strong><em>createTable = false;<\/em><\/strong><br>\n<strong><em>populate = false;<\/em><\/strong><br>\nThe methods to find by id, by name and to list all instances are performed returning the result on the console just for testing purposes.<br>\n.<br>\n<em><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6948\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08.jpg\" alt width=\"1901\" height=\"982\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08.jpg 1901w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08-300x155.jpg 300w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08-768x397.jpg 768w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08-1536x793.jpg 1536w\" sizes=\"(max-width: 1901px) 100vw, 1901px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6948 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201901%20982%22%3E%3C%2Fsvg%3E\" alt width=\"1901\" height=\"982\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201901%20982%22%3E%3C%2Fsvg%3E 1901w\" sizes=\"(max-width: 1901px) 100vw, 1901px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08.jpg 1901w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08-300x155.jpg 300w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08-768x397.jpg 768w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08-1536x793.jpg 1536w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_08.jpg\"><\/em><\/li>\n<\/ol>\n<p>The new persistence layer was tested successfully.<\/p>\n<div>Ok! We&#8217;ve refactored the code to a better design and now it is time to increment the view to show users.<\/div>\n<div>For the &#8220;user table&#8221; we&#8217;ll not implement the CRUD (create, restore, update and delete) GUI interface.<br>\nThis will be done later in the next steps using todo and todoItem use cases.<br>\nFor now, the target is to understand the concepts and test the code we&#8217;ve implemented in this step.<\/div>\n<div><\/div>\n<h2><span class=\"ez-toc-section\" id=\"REFACTORING_appjs_and_User_Router\"><\/span>REFACTORING: app.js and User Router<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<pre>The block highlighted below in the app.js will be moved to the Router.<\/pre>\n<p><strong>ATTENTION:<\/strong><br>\n<strong>This is not the right way of doing things, and we are implementing that way, for now, to evolve later.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre class>const PgSeqlDB = require('.\/models\/persistence\/PgSeqlDB');\ncreateTable = false;\npopulate = false;\nlet pgSeqDB = new PgSeqlDB(createTable);\n\/\/ pgSeqDB.showConfig();\nif (!createTable &amp;&amp; populate) {\n  pgSeqDB.populate();\n}\n<b>if(!createTable &amp;&amp; !populate) {\n  pgSeqDB.findById(1);\n  pgSeqDB.findByName('John Doe');\n  pgSeqDB.findAll();\n}<\/b>\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Remove the highlighted block above from app.js.<\/p>\n<p>Edit routes\\user.js and replace the code with the following:<\/p>\n<pre class>var express = require('express');\nvar router = express.Router();\nconst PgSeqlDB = require('..\/models\/persistence\/PgSeqlDB');\n\n\nrouter.get('\/', function(req, res, next) {\n  \/\/res.render('users', { title: 'Express' });\n  pg = new PgSeqlDB(false,false);\n  return pg.findAll(res);\n});\n\n\nmodule.exports = router;\n<\/pre>\n<p>You app.js shall be like this from the line where PgSeqlDB is declared up to the end.<\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6965\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_10.jpg\" alt width=\"583\" height=\"764\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_10.jpg 583w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_10-229x300.jpg 229w\" sizes=\"(max-width: 583px) 100vw, 583px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6965 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20583%20764%22%3E%3C%2Fsvg%3E\" alt width=\"583\" height=\"764\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20583%20764%22%3E%3C%2Fsvg%3E 583w\" sizes=\"(max-width: 583px) 100vw, 583px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_10.jpg 583w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_10-229x300.jpg 229w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_10.jpg\"><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"REFACTORING_THE_VIEW_TO_SHOW_THE_USER_INSTANCES\"><\/span>REFACTORING THE VIEW TO SHOW THE USER INSTANCES<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Now it is time to refactor the view&#8217;s code to list the users using the persistence class created before.<br>\nEverything needed is ready to go.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Adding_Bootstrap_and_the_Static_Files\"><\/span>Adding Bootstrap and the Static Files<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Notice that the view uses Bootstrap and other references, so it is required to add the respective library.<br>\nCSS, images, Bootstrap and similars are stored under <strong>node\\public<\/strong> folder.<br>\nCopy the content from the source code to your code \u2014 simplest way.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Refactoring_the_userejs_View\"><\/span>Refactoring the user.ejs View<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Edit the users.ejs file and copy the following code:<\/p>\n<h3><span class=\"ez-toc-section\" id=\"usersejs\"><\/span>users.ejs<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n\n&lt;head&gt;\n\t&lt;meta charset=\"utf-8\"&gt;\n\t&lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"&gt;\n\t&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\"&gt;\n\t&lt;meta name=\"description\" content=\"\"&gt;\n\t&lt;meta name=\"author\" content=\"\"&gt;\n\t&lt;title&gt;&lt;%= title %&gt;&lt;\/title&gt;\n\t&lt;!-- Bootstrap core CSS --&gt;\n\t&lt;link href=\"\/stylesheets\/pinegrow\/bootstrap\/css\/bootstrap.css\" rel=\"stylesheet\"&gt;\n\t&lt;!-- Custom styles for this template --&gt;\n\t&lt;link href=\"\/stylesheets\/pinegrow\/starter-template.css\" rel=\"stylesheet\"&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n\t&lt;nav class=\"navbar navbar-expand-md navbar-dark bg-dark fixed-top\"&gt;\n\t\t&lt;a class=\"navbar-brand\" href=\"#\"&gt;node.js&lt;\/a&gt;\n\t\t&lt;ul class=\"navbar-nav\"&gt;\n\t\t\t&lt;li class=\"nav-item dropdown\"&gt;\n\t\t\t\t&lt;a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"navbarDropdownMenuLink22\" data-toggle=\"dropdown\"\n\t\t\t\t\taria-haspopup=\"true\" aria-expanded=\"false\"&gt;Resources&lt;\/a&gt;\n\t\t\t\t&lt;div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdownMenuLink22\"&gt;\n\t\t\t\t\t&lt;a class=\"dropdown-item\" href=\"#\"&gt;Action&lt;\/a&gt;\n\t\t\t\t\t&lt;a class=\"dropdown-item\" href=\"#\"&gt;Another action&lt;\/a&gt;\n\t\t\t\t\t&lt;a class=\"dropdown-item\" href=\"#\"&gt;Something else here&lt;\/a&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t&lt;\/li&gt;\n\t\t&lt;\/ul&gt;\n\t&lt;\/nav&gt;\n\t&lt;div class=\"container\"&gt;\n\t\t&lt;div class=\"row\"&gt;\n\t\t\t&lt;div class=\"col-md-3\"&gt;\n\t\t\t\t&lt;img class=\"border border-0 border-light img-thumbnail w-50\" src=\"..\/..\/images\/todo_150.jpg\" alt=\"\"&gt;\n\t\t\t&lt;\/div&gt;\n\t\t\t&lt;div class=\"align-middle col-md-6 mt-5 text-center\"&gt;\n\t\t\t\t&lt;h1 class=\"m-n3\"&gt;User list&lt;\/h1&gt;\n\t\t\t&lt;\/div&gt;\n\t\t\t&lt;div class=\"col-md-3\"&gt;&lt;\/div&gt;\n\t\t\t&lt;div class=\"col-md-3\"&gt;&lt;\/div&gt;\n\t\t\t&lt;div class=\"col-md-3\"&gt;&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\t\t&lt;div class=\"starter-template\"&gt;&lt;\/div&gt;\n\t\t&lt;div&gt;\n\t\t\t&lt;div class=\"row\" style=\"margin-bottom: 30px; padding-bottom: 10px; border-bottom: 1px solid gray;\"&gt;\n\t\t\t\t&lt;div class=\"col-md-4\"&gt;\n\t\t\t\t\t&lt;h3&gt;Name&lt;\/h3&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t\t&lt;div class=\"col-md-8\"&gt;\n\t\t\t\t\t&lt;h3&gt;Last Update&lt;\/h3&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;% users.forEach(user =&gt; { %&gt;\n\t\t\t&lt;div&gt;\n\t\t\t\t\t&lt;div class=\"row\" style=\"margin-top: 15px;\"&gt;\n\t\t\t\t\t\t\t&lt;div class=\"col-md-4\"&gt;\n\t\t\t\t\t\t\t\t\t&lt;p&gt;&lt;%= user.username %&gt;&lt;\/p&gt;\n\t\t\t\t\t\t\t&lt;\/div&gt;\n\t\t\t\t\t\t\t&lt;div class=\"col-md-4\"&gt;\n\t\t\t\t\t\t\t\t\t&lt;p&gt;&lt;%= user.updatedAt.toLocaleDateString(\"en-US\") %&gt;&lt;\/p&gt;\n\t\t\t\t\t\t\t&lt;\/div&gt;\n\t\t\t\t\t&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\t&lt;% }) %&gt;\n\n\t&lt;\/div&gt;\n\t&lt;!-- \/.container --&gt;\n\t&lt;!-- Bootstrap core JavaScript\n    ================================================== --&gt;\n\t&lt;!-- Placed at the end of the document so the pages load faster --&gt;\n\t&lt;script src=\"\/stylesheets\/pinegrow\/assets\/js\/jquery.min.js\"&gt;&lt;\/script&gt;\n\t&lt;script src=\"\/stylesheets\/pinegrow\/assets\/js\/popper.js\"&gt;&lt;\/script&gt;\n\t&lt;script src=\"\/stylesheets\/pinegrow\/bootstrap\/js\/bootstrap.min.js\"&gt;&lt;\/script&gt;\n&lt;\/body&gt;\n\n&lt;\/html&gt;\n<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"_REFACTORING_THE_PERSISTENCE_LAYER_ONCE_MORE\"><\/span>&nbsp;REFACTORING THE PERSISTENCE LAYER ONCE MORE<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>&nbsp;<\/p>\n<pre class>var Dbconfig = require('..\/..\/config\/config.json');\nvar Sequelize = require('sequelize');\n\n\/**\n * Database service using Sequelize and PostgreSQL.\n *\n * @class PgSeqlDB\n *\/\nclass PgSeqlDB {\n\n    dbconfig;\n    sequelize;\n    createTables = false;\n    userModel;\n\n    configuration() {\n        \/\/ process.env.APP_ENV captures what was set in the run.bat in the line: SET APP_ENV=dev\n        if (process.env.APP_ENV == 'dev') {\n            console.log('[INFO]: database configuration set to development.')\n            return Dbconfig.development;\n        } else if (process.env.APP_ENV == 'prod') {\n            console.log('[INFO]: database configuration set to production.');\n            return Dbconfig.production;\n        } else if (process.env.APP_ENV == 'cloud') {\n            console.log('[INFO]: database configuration set to cloud.');\n            return Dbconfig.cloud;\n        } else if (process.env.APP_ENV == 'test') {\n            console.log('[INFO]: database configuration set to test environment.')\n            return Dbconfig.test;\n        } else {\n            console.log('[WARN]: database configuration not defined, assuming default (dev): ' + Dbconfig.development.database);\n            return Dbconfig.development;\n        }\n    }\n\n\n    constructor(createTables) {\n        this.createTables = createTables;\n        this.dbconfig = this.configuration();\n        this.sequelize = this.connection();\n        this.defineUserModel();\n        this.syncDb(this.createTables);\n    }\n\n    defineUserModel() {\n        this.userModel = this.sequelize.define('User', {\n            id: {\n                type: Sequelize.INTEGER,\n                allowNull: false,\n                autoIncrement: true,\n                primaryKey: true\n            },\n            username: Sequelize.STRING,\n            password: Sequelize.STRING\n        }, {\n            tableName: 'user', \/\/ this will define the table's name\n            \/\/timestamps: false           \/\/ this will deactivate the timestamp columns\n        });\n\n    }\n\n    connection() {\n        console.log('[INFO]: authenticating database: ' + this.dbconfig.database)\n        let sequelize = new Sequelize(this.dbconfig.database, this.dbconfig.username, this.dbconfig.password, {\n            dialect: this.dbconfig.dialect,\n            port: this.dbconfig.port,\n        });\n        sequelize.authenticate(this.dbconfig).then(function () {\n            console.log('[INFO]: database authenticated');\n        }, function (err) {\n            console.log('[EXCP]: database authentication failed due to: ' + err)\n        });\n        return sequelize;\n    }\n\n    \/**\n     * @param  {boolean} createTables if true, creates the tables.\n     *\/\n    syncDb(createTables) {\n        this.sequelize.sync({\n                force: createTables\n            })\n            .then(function (err) {\n                \/\/console.log('[INFO]: sequelize sync done');\n            }, function (err) {\n                console.log('An error occurred while creating the table:', err);\n            });\n    }\n\n\n    insertUser(name, pass) {\n        this.userModel.create({\n            username: name,\n            password: pass\n        }).then(function (user) {\n            console.log('[INFO]: ' + user.dataValues.username + ' persisted');\n        });\n    }\n\n    populate() {\n        this.insertUser(\"John Doe\", \"secret1\");\n        this.insertUser(\"Mary Doe\", \"secret2\");\n        this.insertUser(\"Jane Doe\", \"secret3\");\n    }\n\n    showConfig() {\n        console.log(this.dbconfig);\n    }\n\n    findById(id) {\n        this.userModel.findByPk(id).then(function (user) {\n            console.log('------------------------------------------');\n            console.log('\\n[INFO]: found: ' + user.id + \", \" + user.username + '\\n');\n        });\n    }\n\n    findByName(name) {\n        this.userModel.findAll({\n            where: {\n                username: name\n            }\n        }).then(function (data, err) {\n            if (!data) {\n                console.log('------------------------------------------');\n                console.log('[FAIL]: user instance not found due to: ' + err);\n                console.log('------------------------------------------');\n            } else {\n                console.log('------------------------------------------');\n                \/\/console.log(data);\n                for (let u in data) {\n                    console.log(data[u].dataValues);\n                }\n                console.log('------------------------------------------');\n            }\n        })\n    }\n\n    findAll(res) {\n        this.userModel.findAll().then(function (data, err) {\n            if (!data) {\n                console.log('------------------------------------------');\n                console.log('[FAIL]: user instance not found due to: ' + err);\n                console.log('------------------------------------------');\n            } else {\n                let list = [];\n                for (let u of data) {\n                    list.push(u.dataValues);\n                }\n                return res.render('users', {\n                    title: 'USERS',\n                    users: list\n                });\n\n            }\n        })\n    }\n\n};\n\n\nmodule.exports = PgSeqlDB;\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Notice that the <strong>findAll method<\/strong> was refactored.<br>\nThe <em>console.log<\/em> statement was replaced by the <em>res.render<\/em> block.<br>\nGo to the user.ejs file and look for <strong><em>users<\/em><\/strong> to understand how it works.<\/p>\n<p>&nbsp;<\/p>\n<pre class>    findAll(res) {\n        this.userModel.findAll().then(function (data, err) {\n            if (!data) {\n                console.log('------------------------------------------');\n                console.log('[FAIL]: user instance not found due to: ' + err);\n                console.log('------------------------------------------');\n            } else {\n                let list = [];\n                for (let u of data) {\n                    list.push(u.dataValues);\n                }\n                return res.render('users', {\n                    title: 'USERS',\n                    users: list\n                });\n\n            }\n        })\n    }\n\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Testing_the_User_List\"><\/span>Testing the User List<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Start the app (run.bat).<br>\nOn the browser, point to:<br>\nhttp:\/\/localhost:3000\/users<\/p>\n<p>You get this:<\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6967\" src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg\" alt width=\"1000\" height=\"541\" srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg 1000w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-300x162.jpg 300w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-768x415.jpg 768w\" sizes=\"(max-width: 1000px) 100vw, 1000px\"><\/noscript><img decoding=\"async\" class=\"alignnone size-full wp-image-6967 lazyload\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%20541%22%3E%3C%2Fsvg%3E\" alt width=\"1000\" height=\"541\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%20541%22%3E%3C%2Fsvg%3E 1000w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" data-srcset=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg 1000w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-300x162.jpg 300w, https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11-768x415.jpg 768w\" data-src=\"https:\/\/ultering.com\/it4us\/wp-content\/uploads\/rin544c_2nd_step_11.jpg\"><\/p>\n<p>&nbsp;<\/p>\n<p>The 3rd step will evolve the applied concepts refactoring the code to implement <em>Todo\/TodoItem<\/em> use case.<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"SOURCE_CODE\"><\/span>SOURCE CODE<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Source code to download using&nbsp; Node.js v.16: GitHub, <a href=\"https:\/\/github.com\/alsdias\/node_sequelize_ultering_ml40643_2nd_step\">node_sequelize_ultering_ml40643_2nd_step<\/a><\/p>\n<p><a href=\"https:\/\/ultering.com\/it4us\/?p=2870\"><strong>Next<\/strong><\/a><\/p>\n<p><a href=\"https:\/\/ultering.com\/it4us\/?p=1953\"><strong>Previous<\/strong><\/a><\/p>\n<p><strong>INDEX<\/strong>:<br>\n<a href=\"https:\/\/ultering.com\/it4us\/?p=2729\">NODE.JS: SEQUELIZE SERIES<\/a><\/p>\n<p>&nbsp;<\/p>\n<div style=\"margin-top: 50px;\">&nbsp;<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<!--CusAds0-->\n<div style=\"font-size: 0px; height: 0px; line-height: 0px; margin: 0; padding: 0; clear: both;\"><\/div>","protected":false},"excerpt":{"rendered":"<p>Revision 2022 TARGET Post revised at 2022. CREATING THE VIEW LAYER USING STUBS This step of the project will create a Todo list as shown in the picture above, using Bootstrap. This project evolves from the 1st step. Now, let&#8217;s follow to the 2nd step. Projects need speed, so it goes faster using multiple development &#8230; <a href=\"https:\/\/ultering.com\/it4us\/?p=2010\" class=\"more-link\">Read More<span class=\"screen-reader-text\"> &#8220;NODE.JS: VIEW USING EXPRESS AND SEQUELIZE &#8211; 2ND STEP&#8221;<\/span> &raquo;<\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"categories":[17,26],"tags":[103,102],"class_list":["post-2010","post","type-post","status-publish","format-standard","hentry","category-database","category-javascript","tag-node-js","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=\/wp\/v2\/posts\/2010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2010"}],"version-history":[{"count":6,"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=\/wp\/v2\/posts\/2010\/revisions"}],"predecessor-version":[{"id":7125,"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=\/wp\/v2\/posts\/2010\/revisions\/7125"}],"wp:attachment":[{"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ultering.com\/it4us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}