<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: fentybit</title>
    <description>The latest articles on Forem by fentybit (@fentybit).</description>
    <link>https://forem.com/fentybit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F447682%2F8d8e91ad-32af-48c8-a1f7-659b97071516.png</url>
      <title>Forem: fentybit</title>
      <link>https://forem.com/fentybit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fentybit"/>
    <language>en</language>
    <item>
      <title>CS50 &amp; Note to Self</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sun, 08 May 2022 21:36:21 +0000</pubDate>
      <link>https://forem.com/fentybit/cs50-note-to-self-f2h</link>
      <guid>https://forem.com/fentybit/cs50-note-to-self-f2h</guid>
      <description>&lt;p&gt;At the beginning of this year, I was pondering what new programming languages and frameworks I should learn. Harvard and MIT both provide great courses on Introduction to Computer Science. I decided to take on the Harvard’s &lt;a href="https://pll.harvard.edu/course/cs50-introduction-computer-science?delta=0"&gt;CS50: Introduction to Computer Science&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Table of Contents
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Why CS50?&lt;/li&gt;
&lt;li&gt;Note to Self&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Why CS50? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I always wanted to learn a low-level programming language such as C. CS50 first few weeks materials were introduction to the &lt;a href="https://en.wikipedia.org/wiki/C_(programming_language)"&gt;C programming language&lt;/a&gt;, and sorting algorithms (bubble, merge and selection). I have to say, trying to solve sorting algorithms in modern languages (for example, JavaScript and Python) is much easier compared to C! On top of that, C’s utils function feels a bit cumbersome. &lt;code&gt;malloc&lt;/code&gt;, &lt;code&gt;realloc&lt;/code&gt; and/or &lt;code&gt;free&lt;/code&gt; should be explicitly defined for memory allocation (heap vs. stack). Nonetheless, C (as well as any subsequent low-level programming language) usually gives better time and space complexity when solving algorithms. &lt;/p&gt;

&lt;p&gt;Second part of the CS50 curriculum includes Python, SQL, HTML, CSS, JavaScript and Flask. The goal is to introduce rudimentary back-end and front-end framework. Python characteristic attributes remind me of Ruby’s terseness, Ruby was my first programming language. Both Python and SQL (&lt;a href="https://www.sqlite.org/index.html"&gt;SQLite3&lt;/a&gt;) eventually become the curriculum’s back-end stack while HTML, CSS and JavaScript performing as the front-end stack. &lt;a href="https://flask.palletsprojects.com/en/2.1.x/"&gt;Flask&lt;/a&gt; is the web framework, and I had the chance to learn and implement &lt;a href="https://palletsprojects.com/p/jinja/"&gt;Jinja&lt;/a&gt; template engine. &lt;/p&gt;

&lt;p&gt;This course was a bit more strenuous than I anticipated! First half of the curriculum was not easy to follow. However, I am glad that I successfully completed the course — so I can enjoy my Summer time. But first, I have to do some Spring cleaning. 😎&lt;/p&gt;

&lt;p&gt;Here is my repo on CS50’s weekly assignments. I had so much fun on their first week’s assignment with &lt;a href="https://scratch.mit.edu/"&gt;Scratch&lt;/a&gt;. 😆&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gt6p3d4_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1487604862539890692/pu/img/UrxBBcE2RiMjrrZq.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Spent the whole day making this game with &lt;a href="https://twitter.com/hashtag/mitscratch"&gt;#mitscratch&lt;/a&gt; 😆 first assignment with &lt;a href="https://twitter.com/hashtag/cs50x"&gt;&lt;/a&gt;&lt;a href="https://twitter.com/hashtag/cs50"&gt;#cs50&lt;/a&gt;x &lt;a href="https://twitter.com/hashtag/cs50"&gt;#cs50&lt;/a&gt; 🦖🌮 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      01:54 AM - 30 Jan 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1487605006563823618" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1487605006563823618" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1487605006563823618" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/cs50"&gt;
        cs50
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;This is my personal repository on &lt;a href="https://pll.harvard.edu/course/cs50-introduction-computer-science?delta=0" rel="nofollow"&gt;Harvard's CS50&lt;/a&gt;. I have decided to enroll this course in my interest learning low level programming language (C), Python and getting familiar with Jinja web template engine.&lt;/p&gt;
&lt;h2&gt;
C&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Week 00&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/fentybit/cs50week_00/Taco_Time.sb3"&gt;Scratch: Taco Time&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Week 01&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hello&lt;/li&gt;
&lt;li&gt;Mario (Less)&lt;/li&gt;
&lt;li&gt;Mario (More)&lt;/li&gt;
&lt;li&gt;Cash&lt;/li&gt;
&lt;li&gt;Credit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Week 02&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scrabble&lt;/li&gt;
&lt;li&gt;Readibility&lt;/li&gt;
&lt;li&gt;Caesar&lt;/li&gt;
&lt;li&gt;Substitution&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Week 03&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sort&lt;/li&gt;
&lt;li&gt;Plurality&lt;/li&gt;
&lt;li&gt;Runoff&lt;/li&gt;
&lt;li&gt;Tideman&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Week 04&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Volume&lt;/li&gt;
&lt;li&gt;Filter (Less)&lt;/li&gt;
&lt;li&gt;Recover&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Week 05&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inheritance&lt;/li&gt;
&lt;li&gt;Speller&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Python&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Week 06&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;World Cup Tournament&lt;/li&gt;
&lt;li&gt;Sentimental / Hello&lt;/li&gt;
&lt;li&gt;Sentimental / Mario (Less)&lt;/li&gt;
&lt;li&gt;Sentimental / Cash&lt;/li&gt;
&lt;li&gt;Sentimental / Readability&lt;/li&gt;
&lt;li&gt;DNA&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
SQL&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Week 07&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Songs&lt;/li&gt;
&lt;li&gt;Movies&lt;/li&gt;
&lt;li&gt;Fiftyville (&lt;em&gt;my favorite!&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
HTML, CSS, JavaScript&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Week 08&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trivia&lt;/li&gt;
&lt;li&gt;Homepage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Flask&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Week 09&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Birthdays&lt;/li&gt;
&lt;li&gt;Finance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Week 10 (Final Project)&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fentybit/NoteToSelf"&gt;Note to Self&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/cs50"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





&lt;h3&gt;
  
  
  Note to Self &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Note to Self is my CS50’s final project. It is a simple to-do application that allows users to log their tasks. First time user would be required to register, and returning user needs to log in. The Minimum Viable Product (MVP) of Note to Self is for the user to be able to log chores along with corresponding level of priorities. User will be prompted to record their first task. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XtiNTQah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phdy7z5v5xj1dozqi5bf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XtiNTQah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phdy7z5v5xj1dozqi5bf.gif" alt="first-time-user" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created two tables on &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;todos&lt;/code&gt; with basic schema. Each user has many tasks, and each task belongs to a user. The &lt;code&gt;user_id&lt;/code&gt; foreign key indicates the two tables’ relationship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It took me sometime to get used to Jinja templates on my local IDE, my VSCode linters automatically re-format. I learned from &lt;a href="https://stackoverflow.com/questions/60175608/visual-studio-code-and-jinja-templates"&gt;Stackoverflow&lt;/a&gt; that I had to add &lt;code&gt;"emmet.includeLanguages": {"jinja-html": "html"},&lt;/code&gt; to my &lt;code&gt;settings.json&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Basic validations on &lt;code&gt;/register&lt;/code&gt;, &lt;code&gt;/login&lt;/code&gt; and creating a &lt;code&gt;/new&lt;/code&gt; task are provided. On &lt;code&gt;/register&lt;/code&gt;, user would have to include username, password and username should be unique (no duplication). &lt;code&gt;/login&lt;/code&gt; requires both username and password. A &lt;code&gt;/new&lt;/code&gt; task requires priority and title. Otherwise, the user will not be able to proceed further.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Chw4SHIt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nq5yyuh2b7fxylrmcsmb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Chw4SHIt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nq5yyuh2b7fxylrmcsmb.gif" alt="validation" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I included a logic where as the user logs a new task, the one with higher priority will always comes first (descending order). ☆☆☆ tasks will come before ☆☆ tasks. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1xkIX29n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7woi2xxmesoynipl3ia0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1xkIX29n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7woi2xxmesoynipl3ia0.gif" alt="main" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note to Self was completed in 3-day timeframe from implementing JavaScript, Python, SQL and Bootstrap library. Future cycle of product development as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit. User can only create and read. Ideally, we would like edit and delete functionality.&lt;/li&gt;
&lt;li&gt;Quick Find tab. Over the time, user will have many tasks, and it gets troublesome when the user needs to immediately access a specific task entry. A search bar to quickly type event title and access the journal entry would be useful.&lt;/li&gt;
&lt;li&gt;Current task entry allows priority, title and description attributes. Each entry should have more functionality for the user, such as weather, scheduling, sharing capability, image upload and so on.&lt;/li&gt;
&lt;li&gt;Create a toggle track for dark mode. 😎&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/NoteToSelf"&gt;
        NoteToSelf
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      To-Do application.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Note to Self&lt;/h1&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/NoteToSelfstatic/main.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_1fFH2BM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/fentybit/NoteToSelfstatic/main.gif"&gt;&lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Domain Modeling :: To-Do Lists&lt;/strong&gt;&lt;br&gt;
To-Do Tasks app with Python, Flask and SQL frameworks.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/g6M0QU0pnQc" rel="nofollow"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/cs50-note-to-self-f2h" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
About&lt;/h2&gt;
&lt;p&gt;This is my final project of CS50 (&lt;a href="https://pll.harvard.edu/course/cs50-introduction-computer-science?delta=0" rel="nofollow"&gt;CS50x through edX&lt;/a&gt;), Harvard University's introduction to the intellectual enterprises of computer science and the art of programming. &lt;/p&gt;
&lt;p&gt;Note to Self app is a To-Do Tasks application. First time user is required to register, and returning user needs to log in. The Minimum Viable Product (MVP) of Note to Self is for users to be able to log chores along with correspoding level of priorities.&lt;/p&gt;
&lt;h2&gt;
Project Files&lt;/h2&gt;
&lt;div class="snippet-clipboard-content position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code class="notranslate"&gt;
├── static
│   ├── apology.gif
│   ├── favicon.ico
│   ├── giphy.gif
│   └── styles.css
├── templates
│   ├── apology.html
│   ├── index.html
│   ├── layout.html
│   ├── login.html
│   ├── new.html
│   ├── register.html
│   └── todos.html
├── app.py
│       user flow, business logic
├── helpers.py
│       apology, login_required
├── notetoself.db&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/NoteToSelf"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;External Sources:&lt;br&gt;
&lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giphy.com/"&gt;Giphy&lt;/a&gt;&lt;br&gt;
&lt;a href="https://jinja.palletsprojects.com/en/3.1.x/"&gt;Jinja&lt;/a&gt;&lt;/p&gt;






&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>computerscience</category>
      <category>cs50</category>
      <category>python</category>
      <category>c</category>
    </item>
    <item>
      <title>365 Days of Code Journal</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sun, 20 Feb 2022 20:30:04 +0000</pubDate>
      <link>https://forem.com/fentybit/365-days-of-code-journal-2a3k</link>
      <guid>https://forem.com/fentybit/365-days-of-code-journal-2a3k</guid>
      <description>&lt;p&gt;2021 has been a tumultuous year. I worked full time while attending Flatiron School’s Software Engineering part time program, and officially pivoted my career in tech to become a Full Stack Engineer at RE/MAX (First Engineering Team). It was truly an epic year. 🥳&lt;/p&gt;

&lt;p&gt;However, I have to admit that I also overworked myself. That’s right, I finished the 365 Days of Code challenge. 🥲&lt;/p&gt;




&lt;h4&gt;
  
  
  Table of Contents
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;100 Days of Code&lt;/li&gt;
&lt;li&gt;The Sequel&lt;/li&gt;
&lt;li&gt;Educational Materials&lt;/li&gt;
&lt;li&gt;End of Story&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  100 Days of Code &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It all began with the &lt;code&gt;#100DaysOfCode&lt;/code&gt; challenge. Most junior engineers (including me 🙋🏻‍♀️ ) take on this challenge for fun. Why not? They are all over the Twitter tech universe. When I set the challenge in motion, I was already halfway through my bootcamp. &lt;a href="https://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; was my first exposure to object-oriented programming language and framework. 💎&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jJCKHvm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/tweet_video_thumb/EsoFGxYUwAEoOhG.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 1 of &lt;a href="https://twitter.com/hashtag/100DaysOfCode"&gt;#100DaysOfCode&lt;/a&gt; 👩🏻‍⚕️&lt;br&gt;&lt;br&gt;I wrapped up my Ruby on Rails project assessment!&lt;br&gt;Plan to deploy on Heroku tomorrow. ✌🏼&lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/DEVCommunity"&gt;#DEVCommunity&lt;/a&gt; &lt;br&gt;&lt;a href="https://twitter.com/hashtag/Rails"&gt;#Rails&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      02:59 AM - 26 Jan 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1353900267742191617" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1353900267742191617" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1353900267742191617" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;As soon as our cohort concluded the Rails module, we switched our learning curriculum to JavaScript language and &lt;a href="https://reactjs.org/"&gt;ReactJS&lt;/a&gt; framework. JavaScript is... wild. I remember having to take supplemental courses; &lt;a href="https://www.udemy.com/course/understand-javascript/"&gt;JavaScript: Understanding the Weird Parts&lt;/a&gt; by Anthony Alicea, &lt;a href="https://www.udemy.com/course/javascript-beginners-complete-tutorial/"&gt;The Modern JavaScript Bootcamp Course&lt;/a&gt; by Colt Steele and &lt;a href="https://eloquentjavascript.net/"&gt;Eloquent JavaScript&lt;/a&gt;. They provided a great introduction to understanding JavaScript fundamentals, not to mention the amount of YouTube instructors I had randomly subscribed to. 😅 &lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6sbf2-ex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/tweet_video_thumb/ExgrEVIUcAIjVDP.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 62 of &lt;a href="https://twitter.com/hashtag/100DaysOfCode"&gt;#100DaysOfCode&lt;/a&gt; &lt;br&gt;&lt;br&gt;Officially deployed my Know It All 🌟&lt;br&gt;&lt;br&gt;&lt;a href="https://t.co/JkS4g6M9s3"&gt;lets-know-it-all.netlify.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;Back-End :: Heroku&lt;br&gt;Front-End :: Netlify&lt;br&gt;&lt;br&gt;ps: I was told my app does not work on iOS platform, please let me know if other devs have issues.&lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/JavaScript"&gt;#JavaScript&lt;/a&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/RubyonRails"&gt;#RubyonRails&lt;/a&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/WomenWhoCode"&gt;#WomenWhoCode&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      19:46 PM - 27 Mar 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1375897052987621381" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1375897052987621381" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1375897052987621381" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Two months later, I was able to build an app with Vanilla JavaScript and Rails back-end. I had no idea you could do so much with Vanilla JavaScript! Soon after, I decided to implement my rudimentary JS knowledge on building a &lt;a href="https://fentybit.me/"&gt;personal website&lt;/a&gt;. To be fair, I used &lt;a href="https://pixelarity.com/"&gt;Pixelarity&lt;/a&gt;’s ready-made template. My point is that anyone can do a lot with JavaScript alone. 🙂&lt;/p&gt;

&lt;p&gt;One thing that I realized, I was never alone during my &lt;code&gt;#100DaysOfCode&lt;/code&gt; journey. It ended up triggering many interesting conversations, new Twitter friends and discovering tech stacks from fellow engineers. I felt like the Twitter tech universe was 100% with me. This motivated me to further extend my &lt;code&gt;#100DaysOfCode&lt;/code&gt; challenge to &lt;code&gt;#365DaysOfCode&lt;/code&gt;. Yikes, I know. 😬&lt;/p&gt;




&lt;h3&gt;
  
  
  The Sequel &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I dedicated my best efforts to my final ReactJS project creating a journaling app. I graduated from Flatiron School in May 2021, though my moment of triumph was to finally land my first Engineer role at &lt;a href="https://www.first.io/"&gt;RE/MAX First&lt;/a&gt; soon after. 😭  I started looking for opportunities 4 months prior to graduation. I feel like I need to write a separate blog when it comes to career pivoting. I would say behind a single success, there lie many failures. &lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tTxTP1Ab--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/tweet_video_thumb/E2gE2S2VoAAKIV4.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 124 of &lt;a href="https://twitter.com/hashtag/365DaysOfCode"&gt;#365DaysOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;I PASSED my final assessment with &lt;a href="https://twitter.com/FlatironSchool"&gt;@FlatironSchool&lt;/a&gt;! 🥳&lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/100DaysOfCode"&gt;#100DaysOfCode&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/Rails"&gt;#Rails&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/ReactJS"&gt;#ReactJS&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/MaterialUI"&gt;#MaterialUI&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/DEVCommunity"&gt;#DEVCommunity&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/WomenWhoCode"&gt;#WomenWhoCode&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/FlatironSchoo"&gt;#FlatironSchoo&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      20:18 PM - 28 May 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1398373045727731712" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1398373045727731712" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1398373045727731712" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;I had my moments when I felt like maybe.. I should stop, and simply focus on getting myself acclimated with the new role. Then, I was advised that the first year of being a junior engineer is highly critical. It is an opportunity to learn many stacks, and absorb knowledge from fellow mid and senior engineers. So there I was, spending extra hours after work daily trying to enhance my personal development. RE/MAX offered me a Full Stack Engineer position. I was super stoked. The role aligns with my interests in both realms, front-end and back-end. Flatiron School’s ReactJS was a great introduction to &lt;a href="https://reactnative.dev/"&gt;React Native&lt;/a&gt; mobile development. I spent the first few months learning React Native, a11y (accessibility), &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;, &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; and &lt;a href="https://rspec.info/"&gt;RSpec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I believe diversity and inclusion should be universal to all product platforms including mobile apps. I had the opportunity to spend sometime learning &lt;a href="https://www.udacity.com/course/web-accessibility--ud891"&gt;Web Accessibility by Google&lt;/a&gt;. The course educates developers to approach code design solutions with empathy. When I was introduced to TypeScript, I quickly fell in love with its strict syntactics. I learned TypeScript from basic to intermediate with &lt;a href="https://www.executeprogram.com/"&gt;Execute Program&lt;/a&gt; alongside a supplemental reading, &lt;a href="https://www.oreilly.com/library/view/programming-typescript/9781492037644/"&gt;Programming TypeScript&lt;/a&gt; by Boris Cherny. In my downtime, I like to practice my Vanilla JavaScript with &lt;a href="https://javascript30.com/"&gt;Wes Bos’ Vanilla JS Coding Challenge&lt;/a&gt;. &lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dbvMOtPf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/tweet_video_thumb/E-JBjz1VcAMjpbK.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 219 of &lt;a href="https://twitter.com/hashtag/365DaysOfCode"&gt;#365DaysOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;Can’t believe I made it! &lt;br&gt;&lt;a href="https://twitter.com/hashtag/JavaScript30"&gt;&lt;/a&gt;&lt;a href="https://twitter.com/hashtag/JavaScript"&gt;#JavaScript&lt;/a&gt;30 30/30 Whack a Mole &lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/100DaysOfCode"&gt;#100DaysOfCode&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/DEVCommunity"&gt;#DEVCommunity&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/WomenWhoCode"&gt;#WomenWhoCode&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/JavaScript"&gt;#JavaScript&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      18:58 PM - 31 Aug 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1432779802482659329" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1432779802482659329" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1432779802482659329" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Moving on to back-end stacks and system architecture, I was lucky enough to have the chance to deepen my Ruby knowledge. Rails is the current main back-end stack. Flatiron School introduced us to Ruby on Rails, and its rudimentary knowledge building school projects. While at work, I am super thrilled that I have been exposed to real complex object-oriented domain modeling. &lt;a href="http://rubykoans.com/"&gt;Ruby Koans&lt;/a&gt; helped me with intermittent retrieval practice on Ruby language, syntax and structure. &lt;a href="https://twitter.com/fentybit/status/1433497646392479745"&gt;Practical Object-Oriented Design&lt;/a&gt; by Sandy Metz is an amazing read for all Ruby lovers. My struggle has always been writing &lt;a href="https://rspec.info/"&gt;RSpec&lt;/a&gt; since that was not a part of Flatiron School’s curriculum. To this day, I am still learning new things. Feel free to share if any devs out there have any suggestions on RSpec learning materials. &lt;/p&gt;

&lt;p&gt;This is miscellany. Git commands have always been a common struggle for junior engineers (including me again 🙋🏻‍♀️ ). I ended up taking a side course on &lt;a href="https://www.udemy.com/course/git-and-github-bootcamp/"&gt;Git and GitHub&lt;/a&gt;. 😆  The world of Git is vast indeed. &lt;a href="https://twitter.com/fentybit/status/1443727545610879013"&gt;The Pragmatic Programmer&lt;/a&gt; by David Thomas, Andrew Hunt and &lt;a href="https://www.oreilly.com/library/view/clean-code-a/9780136083238/"&gt;Clean Code&lt;/a&gt; by Robert C. Martin were both instrumental in guiding my daily contribution to my peers. &lt;/p&gt;

&lt;p&gt;While it was all fun deepening my knowledge on front-end and back-end frameworks, I enjoy learning data structures and algorithms. I settled on Colt Steele’s &lt;a href="https://www.udemy.com/course/js-algorithms-and-data-structures-masterclass/"&gt;JS Algorithms and Data Structures&lt;/a&gt; Udemy course. It took me about 3+ months to grasp basic algorithm concepts. I vaguely remember some of the concepts during my undergraduate years. Data structures and algorithms can be frustrating at times, and the key is to not spend more than an hour a day. Be kind to yourself.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yx9aT4lk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/tweet_video_thumb/FB8eD0lVEAMlRd5.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 267 of &lt;a href="https://twitter.com/hashtag/365DaysOfCode"&gt;#365DaysOfCode&lt;/a&gt; &lt;br&gt;&lt;br&gt;Intro to Data Structures and Algorithms. They are collections of values, the relationships among them, and the functions or operations that can be applied to the data. &lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/100DaysOfCode"&gt;#100DaysOfCode&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/DEVCommunity"&gt;#DEVCommunity&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/WomenWhoCode"&gt;#WomenWhoCode&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/GirlsWhoCode"&gt;#GirlsWhoCode&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      14:23 PM - 18 Oct 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1450105133946204168" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1450105133946204168" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1450105133946204168" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Fast forward... 💨  on my last day of 365 days of coding challenge, I decided that this day should not be the last day of my learning ventures. I want to take on the challenge on the theoretical aspects of Computer Science. I want to learn &lt;a href="https://en.wikipedia.org/wiki/C_(programming_language)"&gt;C&lt;/a&gt;, first programming language created in 1972, and maybe another object-oriented language, Phyton. &lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 365 of &lt;a href="https://twitter.com/hashtag/365DaysOfCode"&gt;#365DaysOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;This is it, my last day of 365 days of coding. 😭🎉&lt;br&gt;&lt;br&gt;I have decided to sign up for Harvard's &lt;a href="https://twitter.com/hashtag/CS50"&gt;&lt;/a&gt;&lt;a href="https://twitter.com/hashtag/C"&gt;#C&lt;/a&gt;S50 Introduction to Computer Science as I plan to continue my learning on 2 new languages this year on &lt;a href="https://twitter.com/hashtag/C"&gt;#C&lt;/a&gt; and &lt;a href="https://twitter.com/hashtag/Phyton"&gt;#Phyton&lt;/a&gt;. 🤓&lt;br&gt;&lt;br&gt;&lt;a href="https://t.co/Q7gtHus6hz"&gt;pll.harvard.edu/course/cs50-in…&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      18:07 PM - 24 Jan 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1485675657744977920" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1485675657744977920" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1485675657744977920" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;





&lt;h3&gt;
  
  
  Educational Materials &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Summary of courses and readings I went trough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Courses:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://flatironschool.com/welcome-to-flatiron-school/software-engineering/?utm_source=Google&amp;amp;utm_medium=ppc&amp;amp;utm_campaign=12728169833&amp;amp;utm_content=127574237744&amp;amp;utm_term=flatiron%20school%20software%20engineering&amp;amp;uqaid=513799628786&amp;amp;Cj0KCQiA6NOPBhCPARIsAHAy2zCfu2Z22sXl4hQgGxjnnVoROnk_Vox5I8AfuutK_rJRXE-Ai-eC27MaAmAuEALw_wcB&amp;amp;gclid=Cj0KCQiA6NOPBhCPARIsAHAy2zCfu2Z22sXl4hQgGxjnnVoROnk_Vox5I8AfuutK_rJRXE-Ai-eC27MaAmAuEALw_wcB"&gt;Flatiron School Software Engineering Program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/understand-javascript/"&gt;JavaScript: Understanding the Weird Parts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/javascript-beginners-complete-tutorial/"&gt;The Modern JavaScript Bootcamp Course&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykoans.com/"&gt;Ruby Koans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/git-and-github-bootcamp/"&gt;The Git and GitHub Bootcamp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://javascript30.com/"&gt;JavaScript 30&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.executeprogram.com/"&gt;Execute Program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udacity.com/course/web-accessibility--ud891"&gt;Web Accessibility by Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/js-algorithms-and-data-structures-masterclass/"&gt;JavaScript Algorithms and Data Structures Masterclass&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Readings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eloquentjavascript.net/"&gt;Eloquent JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/programming-typescript/9781492037644/"&gt;Programming TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pragprog.com//titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/clean-code-a/9780136083238/"&gt;Clean Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  End of Story &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Why did I end up writing this blog? I would have preferred technical writing, as I find more joy in writing documentation. Developers live in such a fast-paced setting, especially when it comes to tech ecosystems. We don’t get much time for reflection. This journal is to remind myself that I am grateful for the opportunity to learn and grow. I have learned so much the past 365 days. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Miscellany&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course looking back, I’d be curious which of my tweets is most popular and/or re-tweeted often. Surprisingly, this one tweet when I was having fun with &lt;a href="https://grasshopper.app/"&gt;Grasshopper App&lt;/a&gt; (great intro to JS’ DOM manipulation). I still don’t understand how Twitter analytics work. 😆&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hXw3Qtzo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EtrToMHUYAYR2_O.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--05UwawUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1391059520361615362/JtGUA6A8_normal.jpg" alt="fentybit profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        fentybit
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/fentybit"&gt;@fentybit&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Day 14 of &lt;a href="https://twitter.com/hashtag/100DaysOfCode"&gt;#100DaysOfCode&lt;/a&gt; &lt;br&gt;&lt;br&gt;Sunday Funday with &lt;a href="https://twitter.com/GrasshopperApp"&gt;@GrasshopperApp&lt;/a&gt; 📲&lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/JavaScript"&gt;#JavaScript&lt;/a&gt; &lt;br&gt;&lt;a href="https://twitter.com/hashtag/DEVCommunity"&gt;#DEVCommunity&lt;/a&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/WomenWhoCode"&gt;#WomenWhoCode&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      04:17 AM - 08 Feb 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1358630928709341184" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1358630928709341184" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1358630928709341184" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;







&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>programming</category>
      <category>100daysofcode</category>
      <category>computerscience</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>⚡️ 30 Day Vanilla JS ⚡️</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Wed, 01 Sep 2021 15:49:19 +0000</pubDate>
      <link>https://forem.com/fentybit/30-day-vanilla-js-1nmp</link>
      <guid>https://forem.com/fentybit/30-day-vanilla-js-1nmp</guid>
      <description>&lt;p&gt;I have been meaning to take on &lt;a href="https://javascript30.com/" rel="noopener noreferrer"&gt;Wes Bos' JavaScript30 challenge&lt;/a&gt;, but had no time to spare during my bootcamp regime at Flatiron School. At this moment as I am writing this blog, I already had exposure to Vanilla JS and worked on a &lt;a href="https://dev.to/fentybit/know-it-all-2kpp"&gt;simple trivia app&lt;/a&gt;, &lt;em&gt;Know It All.&lt;/em&gt; There are more to JavaScript that I decided to embark on this #JavaScript30. This blog concludes my journey of 30 Day Vanilla JS Challenge. I had much fun! Thank you Wes Bos. 🙌🏼&lt;/p&gt;




&lt;h3&gt;
  
  
  🥁  Day 1 JavaScript Drum Kit
&lt;/h3&gt;

&lt;p&gt;The goal is to press any of the displayed keys, and it will give you its assigned sound. &lt;code&gt;.wav&lt;/code&gt; sound files are already provided in the starter files. By utilizing &lt;code&gt;querySelector&lt;/code&gt; on &lt;code&gt;event.keyCode&lt;/code&gt;, I was able to adjust the selected element's &lt;code&gt;classList&lt;/code&gt; and attached an &lt;code&gt;addEventListener&lt;/code&gt; on &lt;code&gt;keydown&lt;/code&gt; to trigger the sound.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakm8cfi95sjjetnjso6g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakm8cfi95sjjetnjso6g.gif" alt="JavaScript Drum Kit"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  ⏰  Day 2 CSS + JS Clock
&lt;/h3&gt;

&lt;p&gt;I learned a few new JS prototype methods on &lt;code&gt;getHours()&lt;/code&gt;, &lt;code&gt;getMinutes()&lt;/code&gt; and &lt;code&gt;getSeconds()&lt;/code&gt;. A bit of mathematical calculations required when trying to update the &lt;code&gt;style&lt;/code&gt; in order to &lt;code&gt;transform&lt;/code&gt; the &lt;code&gt;rotate&lt;/code&gt; degree attributes. The &lt;code&gt;setInterval&lt;/code&gt; function will trigger updates every second (or 1000 millisecond).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf071l88i73khlxbkqoz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf071l88i73khlxbkqoz.gif" alt="CSS + JS Clock"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🎨  Day 3 Playing with CSS Variables and JS
&lt;/h3&gt;

&lt;p&gt;Updating CSS variables with JavaScript is pretty cool! Now I know how to declare &lt;code&gt;--base&lt;/code&gt;, &lt;code&gt;--spacing&lt;/code&gt; and &lt;code&gt;--blur&lt;/code&gt; CSS variables and default values under &lt;code&gt;:root&lt;/code&gt; in &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; element. &lt;code&gt;change&lt;/code&gt; and &lt;code&gt;mousemove&lt;/code&gt; event listeners are being utilized to handle changes and update event display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc736d5xpj9ldt8ws6sll.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc736d5xpj9ldt8ws6sll.gif" alt="Playing with CSS Variables and JS"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🫀  Day 4 Array Cardio Day 1
&lt;/h3&gt;

&lt;p&gt;This is a good overview on JS &lt;code&gt;filter()&lt;/code&gt;, &lt;code&gt;map()&lt;/code&gt;, &lt;code&gt;sort()&lt;/code&gt; and &lt;code&gt;reduce()&lt;/code&gt; functions. De-structuring assignment was also introduced, and a bit of refactoring exercise on &lt;code&gt;if else&lt;/code&gt; statement to ternary operator syntax.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6e6yszbb9ljnkitjb70.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6e6yszbb9ljnkitjb70.gif" alt="Array Cardio Day 1"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🌁  Day 5 Flex Panel Gallery
&lt;/h3&gt;

&lt;p&gt;FlexBox CSS has personally been a total nightmare for me, but Wes Bos made it so much fun. 😆&lt;br&gt;
I learned a few new CSS attributes such as &lt;code&gt;display: flex&lt;/code&gt;, &lt;code&gt;transform: translateY(-100%)&lt;/code&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle" rel="noopener noreferrer"&gt;DOMTokenList&lt;/a&gt; &lt;code&gt;toggle()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fneiywupqgr6yylptmn5i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fneiywupqgr6yylptmn5i.gif" alt="Flex Panel Gallery"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  ⚡️  Day 6 AJAX Type Ahead
&lt;/h3&gt;

&lt;p&gt;I had previously done extensive &lt;code&gt;fetch()&lt;/code&gt; requests on my ReactJS/Redux app, &lt;a href="https://dev.to/fentybit/storybook-4p2g"&gt;Storybook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's new for me in this lesson would be to implement &lt;code&gt;RegExp&lt;/code&gt; when typing matching words, and adding both &lt;code&gt;change&lt;/code&gt; and &lt;code&gt;keyup&lt;/code&gt; add event listeners on the search input.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojjhxk0bxrn5spu72p6p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojjhxk0bxrn5spu72p6p.gif" alt="AJAX Type Ahead"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🏃🏻‍♀️  Day 7 Array Cardio Day 2
&lt;/h3&gt;

&lt;p&gt;Good brush up on JavaScript methods &lt;code&gt;some()&lt;/code&gt;, &lt;code&gt;every()&lt;/code&gt;, &lt;code&gt;findIndex()&lt;/code&gt;. I have used &lt;code&gt;new Date()&lt;/code&gt;, but &lt;code&gt;getFullYear()&lt;/code&gt; was new to me. I have been programming with JavaScript for 4 months, and have to admit their prototype methods are endless. 😱&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzuzioy56286gamq1htw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzuzioy56286gamq1htw.gif" alt="Array Cardio Day 2"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  👩🏻‍🎨  Day 8 Fun with HTML5 Canvas
&lt;/h3&gt;

&lt;p&gt;I really love this canvas mouse play with varying line width and &lt;a href="https://www.w3schools.com/colors/colors_hsl.asp" rel="noopener noreferrer"&gt;HSL (Hue, Saturation and Lightness)&lt;/a&gt;. The add event listeners include &lt;code&gt;mousemove&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt;, &lt;code&gt;mouseout&lt;/code&gt; and &lt;code&gt;mousedown&lt;/code&gt; with mouse event attributes defining &lt;code&gt;offsetX&lt;/code&gt; and &lt;code&gt;offsetY&lt;/code&gt;. As a start, I had to define the canvas with its &lt;code&gt;getContext&lt;/code&gt; in &lt;code&gt;2d&lt;/code&gt; and assign its &lt;code&gt;strokeStyle&lt;/code&gt;, &lt;code&gt;lineJoin&lt;/code&gt;, &lt;code&gt;lineCap&lt;/code&gt; and &lt;code&gt;lineWidth&lt;/code&gt;. A &lt;code&gt;draw&lt;/code&gt; function with &lt;code&gt;event&lt;/code&gt; argument triggers hue changes, &lt;code&gt;moveTo&lt;/code&gt;, &lt;code&gt;lineTo&lt;/code&gt;, &lt;code&gt;stroke()&lt;/code&gt; and &lt;code&gt;[lastX, lastY]&lt;/code&gt;. 🖌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8wq88e6mwlrqoxkl8z8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8wq88e6mwlrqoxkl8z8.gif" alt="Fun with HTML5 Canvas"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🛠  Day 9 Dev Tools Domination
&lt;/h3&gt;

&lt;p&gt;I am very used to &lt;code&gt;console.log&lt;/code&gt;, maybe &lt;code&gt;console.dir&lt;/code&gt; and sometimes &lt;code&gt;console.table&lt;/code&gt;. It's good to know that there are others including &lt;code&gt;console.count&lt;/code&gt;, &lt;code&gt;console.warn&lt;/code&gt;, &lt;code&gt;console.error&lt;/code&gt;, &lt;code&gt;console.info&lt;/code&gt; and &lt;code&gt;console.assert&lt;/code&gt;. &lt;code&gt;console.groupCollapsed&lt;/code&gt; and &lt;code&gt;console.groupEnd&lt;/code&gt; are useful when iterating and grouping each instance independently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek0fyu1ipyt2xbn0f2qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek0fyu1ipyt2xbn0f2qw.png" alt="Dev Tools Domination"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  ✔️  Day 10 Hold Shift and Check Checkboxes
&lt;/h3&gt;

&lt;p&gt;I had once done a basic To-Do List app. This one includes a &lt;code&gt;shift&lt;/code&gt; key feature on which it will allow to check all tasks in-between lists. Pretty neat. There are two main variables; one for &lt;code&gt;boolean&lt;/code&gt; value and one for &lt;code&gt;lastItemChecked&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxjamro6dukfkcl82zff.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxjamro6dukfkcl82zff.gif" alt="Hold Shift and Check Checkboxes"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🎥  Day 11 Custom Video Player
&lt;/h3&gt;

&lt;p&gt;I would say that I am very new to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement" rel="noopener noreferrer"&gt;HTMLMediaElement&lt;/a&gt; interface, to be specific the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement" rel="noopener noreferrer"&gt;HTMLVideoElement&lt;/a&gt; elements. The task is to create a basic video player where you can trigger &lt;code&gt;play&lt;/code&gt; / &lt;code&gt;pause&lt;/code&gt; button, adjust &lt;code&gt;volume&lt;/code&gt;, slow / fast &lt;code&gt;motion&lt;/code&gt; and rewind / forward &lt;code&gt;progress&lt;/code&gt; bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47wchhrguvc2kz6gjj3n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47wchhrguvc2kz6gjj3n.gif" alt="Custom Video Player"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  ⌨️  Day 12 Key Sequence Detection (KONAMI CODE)
&lt;/h3&gt;

&lt;p&gt;If you grew up in the 80s and 90s, you are probably familiar with pressing &lt;code&gt;up&lt;/code&gt; &lt;code&gt;up&lt;/code&gt; &lt;code&gt;down&lt;/code&gt; &lt;code&gt;down&lt;/code&gt; &lt;code&gt;left&lt;/code&gt; &lt;code&gt;right&lt;/code&gt; &lt;code&gt;left&lt;/code&gt; &lt;code&gt;right&lt;/code&gt; &lt;code&gt;B&lt;/code&gt; &lt;code&gt;A&lt;/code&gt; and the &lt;code&gt;start&lt;/code&gt; button on the controller is a cheat code in the video gaming industry. I am creating something similar! The &lt;code&gt;secretCode&lt;/code&gt; could be anything, and I utilized &lt;code&gt;window.addEventListener&lt;/code&gt; on &lt;code&gt;keyup&lt;/code&gt; to get a matching keypress sequence. Every time a keypress array combination matches the &lt;code&gt;secretCode&lt;/code&gt;, it will display a &lt;a href="https://www.cornify.com/js/cornify.js" rel="noopener noreferrer"&gt;unicorn&lt;/a&gt; image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8acfdtm87o5itmdo9bz5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8acfdtm87o5itmdo9bz5.gif" alt="Key Sequence Detection (KONAMI CODE)"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  ⏬  Day 13 Slide In on Scroll
&lt;/h3&gt;

&lt;p&gt;The goal is as you are scrolling down the page, an image to slide in. A &lt;code&gt;debounce&lt;/code&gt; function is defined to delay milliseconds upon invocation when I have an add event listener, &lt;code&gt;scroll&lt;/code&gt;. Original state of the images are currently hidden, and as I am scrolling down, I can &lt;code&gt;add&lt;/code&gt; the &lt;code&gt;active&lt;/code&gt; class style. The solution can be as simple as selecting all of the images in a variable, and loop over each one in order to check its &lt;em&gt;truthy&lt;/em&gt; or &lt;em&gt;falsey&lt;/em&gt;. The condition is &lt;em&gt;truthy&lt;/em&gt; as I am reaching half image height in pixel for the image to scroll in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfwrxio3830ekhnzij9l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfwrxio3830ekhnzij9l.gif" alt="Slide In on Scroll"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  💬  Day 14 Object and Arrays - Reference vs. Copy
&lt;/h3&gt;

&lt;p&gt;Another good JS reminder on reference versus copy, &lt;code&gt;Object.assign&lt;/code&gt; and spread operator implementation. I guess that's all I have to say. 😆&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ab2uml0adl6x6qpol0z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ab2uml0adl6x6qpol0z.gif" alt="Object and Arrays - Reference vs. Copy"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🌮  Day 15 LocalStorage and Event Delegation
&lt;/h3&gt;

&lt;p&gt;Our web browser has a built-in &lt;code&gt;localStorage&lt;/code&gt;, and is capable to retain lightweight data inputs including page refresh. I can send each input with &lt;code&gt;localStorage.setItem&lt;/code&gt;. In order to avoid losing &lt;code&gt;items&lt;/code&gt; as page refreshes, I can set &lt;code&gt;items&lt;/code&gt; to &lt;code&gt;localStorage.getItem&lt;/code&gt;. The toggle actions can be triggered with an add event listener, &lt;code&gt;click&lt;/code&gt;, and boolean &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpos9dbp7e8dkwjpbw20a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpos9dbp7e8dkwjpbw20a.gif" alt="LocalStorage and Event Delegation"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🔥  Day 16 CSS Text Shadow Mouse Move Effect
&lt;/h3&gt;

&lt;p&gt;You can play a lot with CSS on &lt;code&gt;offsetWidth&lt;/code&gt; and &lt;code&gt;offsetHeight&lt;/code&gt;. I can set the &lt;code&gt;text.style.textShadow&lt;/code&gt; of various &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; setbacks with various &lt;code&gt;rgba&lt;/code&gt; values. Fairly simple, yet fun!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrdsrafgfepfjshtmmem.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrdsrafgfepfjshtmmem.gif" alt="CSS Text Shadow Mouse Move Effect"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🎸  Day 17 Sorting Band Names without Articles
&lt;/h3&gt;

&lt;p&gt;An array of bands are provided in the &lt;code&gt;bands&lt;/code&gt; array, and the goal is to sort alphabetically while ignoring &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;the&lt;/code&gt; and &lt;code&gt;an&lt;/code&gt;. That means &lt;code&gt;Counterparts&lt;/code&gt; will come before &lt;code&gt;A Skylit Drive&lt;/code&gt; since &lt;code&gt;S&lt;/code&gt; comes after &lt;code&gt;C&lt;/code&gt;. With simple Regex trick, I can utilize matching groups of &lt;code&gt;(a |the |an )/i&lt;/code&gt;. The global &lt;code&gt;-i&lt;/code&gt; denotes insensitive case, and I can iterate each band with a &lt;code&gt;sort&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqzyji7tjqhc12t3aa62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqzyji7tjqhc12t3aa62.png" alt="Sorting Band Names without Articles"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  ⌛️  Day 18 Tally String Times with Reduce
&lt;/h3&gt;

&lt;p&gt;Given a collection of &lt;code&gt;data-time&lt;/code&gt; with minutes and seconds attributes, I want to add all of the given time duration with a &lt;code&gt;reduce&lt;/code&gt; function. For a start, create an array of &lt;code&gt;data-time&lt;/code&gt; collection, iterate each to extract its &lt;code&gt;.dataset.time&lt;/code&gt; and convert it from string type to integer with &lt;code&gt;parseFloat&lt;/code&gt; function. With &lt;code&gt;reduce&lt;/code&gt; function and modulo &lt;code&gt;%&lt;/code&gt; operator, I should be able to retrieve total seconds, and convert it back to hours, minutes and seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5k28pj9n9pd28j1qtaq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5k28pj9n9pd28j1qtaq.gif" alt="Tally String Times with Reduce"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  📸  Day 19 Unreal Webcam Fun
&lt;/h3&gt;

&lt;p&gt;This whole exercise is new to me. I learned there is an add event listener, &lt;code&gt;canplay&lt;/code&gt;. A variable &lt;code&gt;pixels&lt;/code&gt; is retrieved from &lt;code&gt;.getContext('2d')&lt;/code&gt; and &lt;code&gt;.getImageData(0, 0, width, height)&lt;/code&gt;. Later on I can play with the RGB value by adjusting the pixels data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ar7hzeiglvjhhekg1p3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ar7hzeiglvjhhekg1p3.gif" alt="Unreal Webcam Fun"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🎤  Day 20 Native Speech Recognition
&lt;/h3&gt;

&lt;p&gt;While it is not perfect, I am in awe that we can do a speech recognition in the browser without any libraries or external API. I triggered a &lt;code&gt;new SpeechRecognition()&lt;/code&gt;, and set the &lt;code&gt;.interimResults&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in order to accept more inputs. This allows moving on to the next paragraph when a speaker pauses their speech.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1enuu1j39bf4utkboosr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1enuu1j39bf4utkboosr.gif" alt="Native Speech Recognition"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🧭  Day 21 Geolocation based Speedometer and Compass
&lt;/h3&gt;

&lt;p&gt;This application would need an iOS Simulator, and it has a built-in speed and compass automation. For example use case, the speed displayed mimics the behavior of a city bicycle ride. &lt;code&gt;navigator.geolocation.watchPosition&lt;/code&gt; is invoked to update the arrow and speed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.arrow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.speed-value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watchPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;arrow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`rotate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;deg)`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf96sl189k7npzkus09q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf96sl189k7npzkus09q.gif" alt="Geolocation based Speedometer and Compass"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔗  Day 22 Follow Along Links
&lt;/h3&gt;

&lt;p&gt;The goal would be to highlight all of the links as I hover over the page. First thing I used &lt;code&gt;querySelectorAll&lt;/code&gt; on &lt;code&gt;"a"&lt;/code&gt; link attributes. I can add an event listener &lt;code&gt;mouseenter&lt;/code&gt; and invoke a function to highlight a link. Inside this function, I can utilize &lt;code&gt;getBoundingClientRect()&lt;/code&gt; and it provides &lt;code&gt;bottom&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; properties. With all of these coordinate elements, I can assign each &lt;code&gt;style.width&lt;/code&gt;, &lt;code&gt;style.height&lt;/code&gt; and &lt;code&gt;style.transform&lt;/code&gt; pixels accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydukekulpyaq7z3j4yuj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydukekulpyaq7z3j4yuj.gif" alt="Follow Along Links"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🗣  Day 23 Speech Synthesis
&lt;/h3&gt;

&lt;p&gt;This is akin to building a simple screen reader. &lt;code&gt;SpeechSynthesisUtterance&lt;/code&gt; carries language, text, voice, volume, pitch and other attributes. I can add an event listener &lt;code&gt;voiceschanged&lt;/code&gt; on &lt;code&gt;speechSynthesis&lt;/code&gt; and add a function in order to select a voice. For this lesson, I will limit our voices selections strictly to english language. A &lt;code&gt;boolean&lt;/code&gt; truthy and falsey value can be utilized on a toggle function on the &lt;code&gt;stop&lt;/code&gt; and &lt;code&gt;speak&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygoj3iwqtrk5ajecvm6h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygoj3iwqtrk5ajecvm6h.gif" alt="Speech Synthesis"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🗒  Day 24 Sticky Nav
&lt;/h3&gt;

&lt;p&gt;It would be nice to have the top nav bar to stay as a user scrolling down the page. The effort is less on setting the script aside from checking a condition when &lt;code&gt;window.scrollY&lt;/code&gt; is more than top of the nav bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizp4aa3nse6g9rqttmh0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizp4aa3nse6g9rqttmh0.gif" alt="Sticky Nav"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🥍  Day 25 Event Capture, Propagation, Bubbling and Once
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;addEventListener&lt;/code&gt; has edge cases. The event bubbling can occur when I capture a selected element. If it happens to be a child element, it should also invoke its parent elements. I can apply similar behavior from parent element to its children elements by adding a key value, &lt;code&gt;capture: true&lt;/code&gt;. When I select a parent element, it will run the function all the way down calling all of its children elements. &lt;code&gt;e.stopPropagation()&lt;/code&gt; can stop this event bubbling. Once implemented, when I select the child element, it will not trigger its parent elements. The &lt;code&gt;once: true&lt;/code&gt; only allows a one-time add event listener.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fns1c0x63ch6nbngyr494.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fns1c0x63ch6nbngyr494.gif" alt="Event Capture, Propagation, Bubbling and Once"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🪢  Day 26 Stripe Follow Along Dropdown
&lt;/h3&gt;

&lt;p&gt;This is a creative way to set up a div element where each dropdown follows its respective links sizes. A function can be invoked along with &lt;code&gt;mouseenter&lt;/code&gt; and &lt;code&gt;mouseleave&lt;/code&gt; add event listeners. It is as simple as adding &lt;code&gt;css&lt;/code&gt; class as I click (or hover above) the link, and remove the class as I move away (or hover away from) the link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ful3wxegq0yo5y6m9p32v.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ful3wxegq0yo5y6m9p32v.gif" alt="Stripe Follow Along Dropdown"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🥍  Day 27 Click and Drag to Scroll
&lt;/h3&gt;

&lt;p&gt;There will be four add event listeners, &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseleave&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt; and &lt;code&gt;mousemove&lt;/code&gt;. I can set the &lt;code&gt;isDown&lt;/code&gt; variable as boolean, and set it as &lt;code&gt;false&lt;/code&gt; on both &lt;code&gt;mouseleave&lt;/code&gt; and &lt;code&gt;mouseup&lt;/code&gt; when it is no longer on the clicked state. For the &lt;code&gt;mousemove&lt;/code&gt; add event listener, if the &lt;code&gt;isDown&lt;/code&gt; is false, I can stop the function from running. I had to extract the &lt;code&gt;event.pageX&lt;/code&gt; value in order to do a bit of math calculations as sliding horizontally with the &lt;code&gt;.offsetLeft&lt;/code&gt; and &lt;code&gt;.scrollLeft&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flw0k9pepq5undl8alm45.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flw0k9pepq5undl8alm45.gif" alt="Click and Drag to Scroll"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🏎  Day 28 Video Speed Controller UI
&lt;/h3&gt;

&lt;p&gt;This challenge is an extension of day 11 task on custom video player. When I am watching a youtube video, it's normal to adjust the video speed. This is exactly that! There is a lot more on playing around with math calculations in order to set the playback rate, and I can encapsulate this behavior through a function which would be invoked through an add event listener, &lt;code&gt;mousemove&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ibv0g1354n2c7pw1ezq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ibv0g1354n2c7pw1ezq.gif" alt="Video Speed Controller UI"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  ⌚️  Day 29 Countdown Clock
&lt;/h3&gt;

&lt;p&gt;Similar approach to day 2 challenge. Convert the seconds available to minutes and hours, and set a &lt;code&gt;.reset()&lt;/code&gt; function whenever the add event listener &lt;code&gt;click&lt;/code&gt; or &lt;code&gt;submit&lt;/code&gt; a new selection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixgqqfrfizwv26px6rxa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixgqqfrfizwv26px6rxa.gif" alt="Countdown Clock"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🐰  Day 30 Whack A Mole Game
&lt;/h3&gt;

&lt;p&gt;This is probably my most favorable one, and of course it's a game with plain JS. 😆&lt;/p&gt;

&lt;p&gt;There are a few functions providing random time, random holes where the mole showing up, and adding score when user successfully whack the mole.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuouz8ckf9yzbuo6mfwc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuouz8ckf9yzbuo6mfwc.gif" alt="Whack A Mole Game"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;center&gt;[**fentybit**](https://fentybit.me/) | [GitHub](https://github.com/fentybit) | [Twitter](https://twitter.com/fentybit) | [LinkedIn](https://www.linkedin.com/in/fentybit/)&lt;/center&gt;

</description>
      <category>javascript</category>
      <category>firstyearincode</category>
      <category>100daysofcode</category>
      <category>webdev</category>
    </item>
    <item>
      <title>First-fiddle on TypeScript </title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sun, 01 Aug 2021 23:52:17 +0000</pubDate>
      <link>https://forem.com/fentybit/first-fiddle-on-typescript-3ni7</link>
      <guid>https://forem.com/fentybit/first-fiddle-on-typescript-3ni7</guid>
      <description>&lt;p&gt;I have spent the past few weeks diving in to &lt;strong&gt;TypeScript&lt;/strong&gt;. It has been fun! 😆 TypeScript is a superset of JavaScript, that means it carries all of the JS syntax, including some new syntax as well. Variables in TypeScript have static types. Types come after a &lt;code&gt;:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;TypeScript knows the types of built-in JavaScript functions and methods. While any code with valid syntax typically runs in JavaScript, code must have valid &lt;em&gt;syntax&lt;/em&gt; and valid &lt;em&gt;type check&lt;/em&gt; in order to run in TypeScript.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt;  &lt;code&gt;syntax check&lt;/code&gt; → &lt;code&gt;execution&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt;  &lt;code&gt;syntax check&lt;/code&gt; → &lt;code&gt;type check&lt;/code&gt; → &lt;code&gt;execution&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example in TypeScript, &lt;code&gt;a + b&lt;/code&gt; is a valid syntax. However, if &lt;code&gt;a&lt;/code&gt; is a &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; is a &lt;code&gt;boolean&lt;/code&gt;, then &lt;code&gt;a + b&lt;/code&gt; will not fulfill a valid &lt;code&gt;type check&lt;/code&gt;. This results in a &lt;em&gt;type error&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic types
&lt;/h2&gt;

&lt;p&gt;To declare our own names for types, we can use the &lt;code&gt;type&lt;/code&gt; keyword. It is similar to declaring a variable &lt;code&gt;let&lt;/code&gt;. By convention, user-defined type names are &lt;em&gt;UpperCamelCased&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CarrotCake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CarrotCake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;It is delicious&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 'It is delicious'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Types are only used during &lt;em&gt;type checking&lt;/em&gt; prior to &lt;em&gt;execution&lt;/em&gt;. The declaration of &lt;code&gt;type CarrotCake = string&lt;/code&gt; is a TypeScript syntax. The technical jargon is &lt;em&gt;'type erasure'.&lt;/em&gt; It is solely used for &lt;em&gt;type checking&lt;/em&gt;, and later on discarded from the compiled output. Types are not exclusive to only &lt;em&gt;variables&lt;/em&gt;, but also to &lt;em&gt;function types&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;HowManyEggsForACake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;egg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;redVelvetCake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;egg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;egg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; eggs to start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HowManyEggsForACake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redVelvetCake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// '2 eggs to start'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can implement similar de-structuring assignment on JavaScript to TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;makeCake&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;makeCake&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sponge Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// 'Sponge Cake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Arrays
&lt;/h2&gt;

&lt;p&gt;I like the fact that TypeScript allows the use of an &lt;em&gt;'array of data'&lt;/em&gt; type for &lt;em&gt;function arguments&lt;/em&gt; and &lt;em&gt;function return values&lt;/em&gt;. In the example below, function arguments contain an array of strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;arrayOfCakes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;string[]&lt;/code&gt; is syntactically identical to &lt;code&gt;Array&amp;lt;string&amp;gt;&lt;/code&gt;. This syntax, &lt;code&gt;let otherCakes: Array&amp;lt;string&amp;gt; = ['Banana bread', 'Bebinca']&lt;/code&gt;, is also perfectly valid. Furthermore, I can make an &lt;em&gt;'array of arrays of data'&lt;/em&gt;. Example use of case as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrayOfCakes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Birthday Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;White Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
&lt;span class="c1"&gt;// optionally, you can write (string[])[]&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;namesAndCakes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;][]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;namesAndCakes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angel Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Apple Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]);&lt;/span&gt;
&lt;span class="c1"&gt;// ['Angel Cake', 'Apple Cake'];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inference
&lt;/h2&gt;

&lt;p&gt;We can certainly avoid writing types. This is called &lt;em&gt;type inference&lt;/em&gt;, and TypeScript &lt;em&gt;infers&lt;/em&gt; types. Inference means that the compiler determines the types for us. Types does not necessarily differ from place to place. Every type can be used anywhere that types are allowed. Such as, &lt;code&gt;string&lt;/code&gt; can be a type of a variable, a function argument, or a function's return value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// 'cupcake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript has &lt;em&gt;generic function inference&lt;/em&gt;, and this allows us to call function many times without specifying the type parameters. We can name our generic type parameter &lt;code&gt;T&lt;/code&gt;, and you can use any name you like. Type safety will still be maintained throughout code execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cakeSample&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;cakeSample&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="nx"&gt;cakeSample&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Walnut Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Orange Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fruit Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// [true, 'Orange Cake']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Type error
&lt;/h2&gt;

&lt;p&gt;In JavaScript, there is a common symptom of &lt;code&gt;undefined&lt;/code&gt; error from a function. TypeScript's object types inform back of any type errors during compilation. This helps to identify early rather than failing in production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ingredient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;delicious&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lemoncake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ingredient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delicious&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;lemoncake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;delicious&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bundt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ingredient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chocolate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// type error: missing { delicious: boolean } in type but required in type 'Cake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Literal types
&lt;/h2&gt;

&lt;p&gt;While we have seen basic types such as &lt;code&gt;boolean&lt;/code&gt; and &lt;code&gt;string&lt;/code&gt;, every concrete number is also a type. A variable of type &lt;code&gt;1&lt;/code&gt; can only hold the number &lt;code&gt;1&lt;/code&gt;. It can not hold number &lt;code&gt;2&lt;/code&gt;, this is a compile-time type error. Type &lt;code&gt;1&lt;/code&gt; here is a &lt;em&gt;literal number type&lt;/em&gt;. We can combine &lt;em&gt;literal types&lt;/em&gt; with unions to allow only certain values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;uno&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;one&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unoDos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;unoDos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 2&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;deliciousCake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Biscuit Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angel Food Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Carrot Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;aCake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;deliciousCake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hazelnut Mousse Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;aCake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// type error: type "Hazelnut Mousse Cake" is not assignable to type 'deliciousCake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tuples
&lt;/h2&gt;

&lt;p&gt;This is a new syntax to my TypeScript learning, &lt;em&gt;tuples&lt;/em&gt;. They are arrays of fixed length, in which each type is defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;trays&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pound Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;trays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// 'Pound Cake'&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;platter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vanilla Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// type error: target requires 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Type unions
&lt;/h2&gt;

&lt;p&gt;As an extension of JavaScript, TypeScript is able to add static types to existing JavaScript code. The &lt;code&gt;a | b&lt;/code&gt; syntax means either type &lt;code&gt;a&lt;/code&gt; or type &lt;code&gt;b&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isCake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;isCake&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Butter Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chiffon Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]);&lt;/span&gt;
&lt;span class="c1"&gt;// ['Butter Cake', 'Chiffon Cake']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a &lt;em&gt;type unsoundness&lt;/em&gt; that I found on TypeScript. We understand that we can assign our array to a new variable of type &lt;code&gt;(string | number)[]&lt;/code&gt;. If an array contains only strings, this particular array of &lt;code&gt;string | number&lt;/code&gt; just happens to have no numbers in it right now. Our array variables have different types, but the underlying array is the same. If I were to push a number onto the strings array, weirdly TypeScript allows this. This clearly violates the &lt;code&gt;deliciousCakes&lt;/code&gt; variable's &lt;code&gt;string[]&lt;/code&gt; type!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;deliciousCakes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cheesecake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strawberry Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cakeLovers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deliciousCakes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;cakeLovers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cakeLovers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ['Cheesecake', 'Strawberry Cake', 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;any&lt;/code&gt; type would be another example of &lt;em&gt;type unsoundness&lt;/em&gt; in TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Coffee Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myCake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;myCake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 'Coffee Cake'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Coffee Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yourCake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;yourCake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 'Coffee Cake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We defined &lt;code&gt;cake&lt;/code&gt; a string type, 'Coffee Cake'. We can put a string in an &lt;code&gt;any&lt;/code&gt;, then assign it to a variable of type &lt;code&gt;number&lt;/code&gt;. This is wrong, but it will not cause a &lt;em&gt;type error&lt;/em&gt;. Another way to approach this would be to utilize the &lt;code&gt;unknown&lt;/code&gt; type. We use &lt;code&gt;unknown&lt;/code&gt; to represent values of which type is not known yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Coffee Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myCake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;myCake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// type error:  Type 'cake' is not assignable to type 'string'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Coffee Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myCake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;myCake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 'Coffee Cake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can not use &lt;code&gt;unknown&lt;/code&gt; where TypeScript expects a &lt;code&gt;string&lt;/code&gt; or any other type. This will give you a type error. One way to make &lt;code&gt;unknown&lt;/code&gt; useful is to use conditional narrowing the unknown back to a &lt;code&gt;string&lt;/code&gt; type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nullish coalescing
&lt;/h2&gt;

&lt;p&gt;In TypeScript, following values are equivalent of &lt;code&gt;false&lt;/code&gt; — &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;0n&lt;/code&gt;, &lt;code&gt;''&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, and &lt;code&gt;NaN&lt;/code&gt;. It gets tricky when..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;numberOfCake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;numberOfCake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not fully accurate as &lt;code&gt;0&lt;/code&gt; is a number too, and &lt;code&gt;numberOfCake(0)&lt;/code&gt; should be returning &lt;code&gt;0&lt;/code&gt;. There is a new features called &lt;strong&gt;nullish coalescing&lt;/strong&gt; in 2019 ECMAScript. The &lt;em&gt;nullish coalescing&lt;/em&gt; operator is &lt;code&gt;??&lt;/code&gt;, and it is similar to JavaScript logical OR operator, &lt;code&gt;||&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bananaBread&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;marbleCake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appleCrumble&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appleCrumble&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;financier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;financier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;caramel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;numberOfCake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;numberOfCake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Nullish coalescing&lt;/em&gt; does not consider &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;''&lt;/code&gt; as &lt;em&gt;falsey&lt;/em&gt;. It is only used for checking &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;, which means if we are getting &lt;code&gt;false&lt;/code&gt;, that is because &lt;code&gt;false&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional chaining
&lt;/h2&gt;

&lt;p&gt;Let's start with a &lt;code&gt;Cake&lt;/code&gt; type, and each cake has ingredients, but only sometimes. The &lt;code&gt;Ingredients&lt;/code&gt; type have nuts, but only sometimes. If we want to compile a list of cakes' nuts, &lt;code&gt;Lamingtons&lt;/code&gt; will not cause a problem since the cake's nuts is &lt;code&gt;undefined&lt;/code&gt;. However, &lt;code&gt;Lemon Yoghurt Cake&lt;/code&gt;'s nuts will pose a problem. Since its ingredients is &lt;code&gt;undefined&lt;/code&gt;, asking for &lt;code&gt;ingredients.nuts&lt;/code&gt; will cause a &lt;em&gt;type error.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ingredients&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Ingredients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;egg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;nuts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cake&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Walnut Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;egg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;nuts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;walnuts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lamingtons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;egg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;nuts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lemon Yoghurt Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;cakes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;nuts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ['walnuts', undefined, undefined]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional chaining comes to the rescue, &lt;code&gt;?.&lt;/code&gt;. It checks whether the object is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. If it is, the expression will return &lt;code&gt;undefined&lt;/code&gt;. If it is not, it will return the value of the object's property. With &lt;code&gt;?.&lt;/code&gt;, we can securely access properties and sub-properties of an object that may be &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. &lt;em&gt;Important to note&lt;/em&gt;, even if it's &lt;code&gt;null&lt;/code&gt;, it will still return &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  As
&lt;/h2&gt;

&lt;p&gt;TypeScript does not allow an object type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Battenberg Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;diameter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// type error: property 'cake' does not exist on type '{}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use &lt;code&gt;as&lt;/code&gt; to build a cake object, starting with the empty object &lt;code&gt;{}&lt;/code&gt;. We are able to surpass the normal type checking, and have the compiler to treat our cake as an object type &lt;code&gt;{name: string, diameter: number}&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;diameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Battenberg Cake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;diameter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// {name: 'Battenberg Cake', diameter: 10}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;as&lt;/code&gt; is dangerous as it overrides the type system, and we lose this &lt;em&gt;type check&lt;/em&gt; safety. For example, we can tell TypeScript that a number is a string. &lt;code&gt;as&lt;/code&gt; overrides that, and now the types are just wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aCakeString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cake&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;aCakeString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While my knowledge exposure to TypeScript is minimal, I am super excited to implement this new skill to a real application. I feel TypeScript gives a bit more rigidity to the liberal JavaScript. Thanks TypeScript and many cake types discovery, it's nice getting to know ya! 🍰&lt;/p&gt;






&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>devjournal</category>
      <category>womenintech</category>
    </item>
    <item>
      <title>Storybook</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Wed, 26 May 2021 15:32:02 +0000</pubDate>
      <link>https://forem.com/fentybit/storybook-4p2g</link>
      <guid>https://forem.com/fentybit/storybook-4p2g</guid>
      <description>&lt;p&gt;This is it. 🥺&lt;/p&gt;

&lt;p&gt;This is module 5. 🤓&lt;/p&gt;

&lt;p&gt;This is my &lt;strong&gt;last&lt;/strong&gt; module at Flatiron School. 😱&lt;/p&gt;

&lt;p&gt;What a journey it has been, 10 months of coding from building a &lt;a href="https://dev.to/fentybit/api-cli-space-exploration-108f"&gt;Command Line Interface (CLI)&lt;/a&gt;, &lt;a href="https://dev.to/fentybit/sinatra-x-street-fighter-1hgl"&gt;Sinatra&lt;/a&gt;, &lt;a href="https://dev.to/fentybit/plan-my-md-visit-c0l"&gt;Ruby on Rails&lt;/a&gt;, &lt;a href="https://dev.to/fentybit/know-it-all-2kpp"&gt;Vanilla JavaScript&lt;/a&gt; and now, &lt;strong&gt;ReactJS/Redux&lt;/strong&gt;. I have grown so much, and am truly excited to learn more languages, frameworks and libraries upon graduation. While my previous mod projects encompass personal interests of mine (from space exploration, Street Fighter, tele-health platform to trivia game app), I have kept this particular idea until the very end. &lt;/p&gt;

&lt;p&gt;I have been a long-advocate for having a meaningful connection through self-reflection. Having a digital journaling app to log events, places, moods, and self-reflections from different points of view would fulfill my personal pursuits of journaling experience. While some journal apps I have seen simply record special memories and events, some focus more on mental health, mindfulness and self-care. I have decided to approach this app build with basic features of recorded events and necessary attributes. Future improvements can possibly include mood tracker with A.I. collecting info on how the user is doing. After dedicating sometime to research on a few journal apps such as &lt;a href="https://apps.apple.com/us/app/reflectly-journal-ai-diary/id1241229134" rel="noopener noreferrer"&gt;Reflectly&lt;/a&gt;, &lt;a href="https://diaroapp.com/" rel="noopener noreferrer"&gt;Diaro&lt;/a&gt;, &lt;a href="https://daylio.net/" rel="noopener noreferrer"&gt;Daylio&lt;/a&gt;, and others, I emulate most of my app build features following &lt;a href="https://dayoneapp.com/" rel="noopener noreferrer"&gt;Day One&lt;/a&gt; and &lt;a href="https://www.notion.so/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;. I love the overall user flow from Day One, and the postulation of &lt;em&gt;all-in-one workspace&lt;/em&gt; from Notion. There are a couple of technical challenges I would like to pursue personally such as working with Google Maps API.&lt;/p&gt;




&lt;h4&gt;
  
  
  Table of Contents
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;User Story and Model Associations&lt;/li&gt;
&lt;li&gt;Rails API Back-End&lt;/li&gt;
&lt;li&gt;Routes, Controllers and Serializers&lt;/li&gt;
&lt;li&gt;React — Getting Started&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Action&lt;/code&gt; → &lt;code&gt;Reducer&lt;/code&gt; → &lt;code&gt;New State&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Nested Routes in React Router&lt;/li&gt;
&lt;li&gt;Google Maps Platform APIs&lt;/li&gt;
&lt;li&gt;Material-UI and Lessons Learned&lt;/li&gt;
&lt;li&gt;Build Status and Future Improvement&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  1. User Story and Model Associations &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;I brainstormed my app through building wireframes at first. The exercise helped me to collect some understanding of model relationships, necessary attributes, components and overall user interface. I realized that my wireframing exercise eventually became an overarching goal. 🥺&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bsav7almji7lueyuufw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bsav7almji7lueyuufw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the user begins their journaling experience, the user will be prompted to fill out a form of an &lt;em&gt;entry event&lt;/em&gt;. Each entry event carries &lt;em&gt;event title, date, time, location, vibe, description and photo&lt;/em&gt;. The user can personalize each entry by assigning a &lt;em&gt;category&lt;/em&gt;. After several entries and categories propagated over some time, when the user selects a category, it should list its respective event entries. For example, under category &lt;em&gt;'restaurants'&lt;/em&gt;, the user will see all of their food ventures entries. As the user selects a specific entry, it will prompt a &lt;em&gt;show page&lt;/em&gt; specific to the selected event &lt;code&gt;id&lt;/code&gt;. The user can reflect all of their journal entries through various points of view: &lt;em&gt;calendar&lt;/em&gt;, &lt;em&gt;map&lt;/em&gt; and &lt;em&gt;photos&lt;/em&gt;. For example, if the user selects a map view, it will show all pinpoints of recorded places. The user can select each pinpoint, and it should also display event details in correspond to the selected entry &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F87h3f8pylh2kc1ohqum0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F87h3f8pylh2kc1ohqum0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are 4 main models &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Category&lt;/code&gt;, &lt;code&gt;Event&lt;/code&gt; and &lt;code&gt;Image&lt;/code&gt; with their associations as follows.&lt;/p&gt;

&lt;p&gt;user &lt;code&gt;has_many&lt;/code&gt; :events &lt;/p&gt;

&lt;p&gt;category &lt;code&gt;has_many&lt;/code&gt; :events&lt;/p&gt;

&lt;p&gt;event &lt;code&gt;belongs_to&lt;/code&gt; :user&lt;br&gt;
event &lt;code&gt;belongs_to&lt;/code&gt; :category&lt;br&gt;
event &lt;code&gt;has_one&lt;/code&gt; :image&lt;/p&gt;

&lt;p&gt;image &lt;code&gt;belongs_to&lt;/code&gt; :event&lt;/p&gt;


&lt;h4&gt;
  
  
  2. Rails API Back-End &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;I have built Rails API previously, and surprisingly... I have only a small memory recollection. 😅  &lt;/p&gt;

&lt;p&gt;I initiated the prompt command &lt;code&gt;rails new Storybook_backend --database=postgresql --api --no-test-framework&lt;/code&gt;. The &lt;code&gt;--api&lt;/code&gt; will remove unnecessary features and middleware with controllers inheriting from &lt;code&gt;ActionController::API&lt;/code&gt;, and &lt;code&gt;--no-test-framework&lt;/code&gt; will remove any testing framework. PostgreSQL database is helpful when I need to deploy on Heroku. Make sure to include gem &lt;code&gt;rack-cors&lt;/code&gt; and &lt;code&gt;bcrypt&lt;/code&gt; when &lt;code&gt;bundle install&lt;/code&gt;. The next step is to generate Active Record Models for &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Category&lt;/code&gt;, &lt;code&gt;Event&lt;/code&gt; and &lt;code&gt;Image&lt;/code&gt;, and execute &lt;code&gt;rails db:create &amp;amp;&amp;amp; rails db:migrate&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mi"&gt;2021_05_24_194555&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bigint&lt;/span&gt; &lt;span class="s2"&gt;"category_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bigint&lt;/span&gt; &lt;span class="s2"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"title"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt; &lt;span class="s2"&gt;"date"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"location"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"latitude"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"longitude"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"vibe"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"description"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"category_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"index_events_on_category_id"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"index_events_on_user_id"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"images"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bigint&lt;/span&gt; &lt;span class="s2"&gt;"event_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"url"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"event_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"index_images_on_event_id"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"username"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"password_digest"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"firstname"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"lastname"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;add_foreign_key&lt;/span&gt; &lt;span class="s2"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"categories"&lt;/span&gt;
  &lt;span class="n"&gt;add_foreign_key&lt;/span&gt; &lt;span class="s2"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt;
  &lt;span class="n"&gt;add_foreign_key&lt;/span&gt; &lt;span class="s2"&gt;"images"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"events"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I am content with my &lt;code&gt;schema.rb&lt;/code&gt; build, and it is always a good practice to test my models and associations with &lt;code&gt;rails console&lt;/code&gt;.&lt;/p&gt;


&lt;h4&gt;
  
  
  3. Routes, Controllers and Serializers &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;I provided only the required back-end routes for my front-end's asynchronous &lt;code&gt;fetch()&lt;/code&gt; actions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:v1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'/login'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'auth#create'&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'users#profile'&lt;/span&gt;

      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Moving on to my controllers, I spent most of my time applying &lt;strong&gt;JWT&lt;/strong&gt; &lt;em&gt;(JSON Web Tokens)&lt;/em&gt; in my &lt;code&gt;ApplicationController&lt;/code&gt;, &lt;code&gt;Api::V1::UsersController&lt;/code&gt; and &lt;code&gt;Api::V1::AuthController&lt;/code&gt;. The &lt;code&gt;ApplicationController&lt;/code&gt; defines &lt;code&gt;JWT.encode&lt;/code&gt;, &lt;code&gt;JWT.decode&lt;/code&gt; and most importantly &lt;code&gt;authorized&lt;/code&gt; instance method to barricade access to the other controllers. Only an &lt;em&gt;authorized&lt;/em&gt; user can access other controllers. The &lt;code&gt;AuthController&lt;/code&gt; &lt;em&gt;create action&lt;/em&gt; will provide authentication for users logging in, and the &lt;code&gt;UsersController&lt;/code&gt; &lt;em&gt;create action&lt;/em&gt; allows a new user signing up.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Api::V1::EventsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;skip_before_action&lt;/span&gt; &lt;span class="ss"&gt;:authorized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt; 
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:category&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
      &lt;span class="vi"&gt;@category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_or_create_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

      &lt;span class="vi"&gt;@event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;vibe: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:vibe&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;date: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:date&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;time: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:time&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;location: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:location&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:latitude&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:longitude&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;category_id: &lt;/span&gt;&lt;span class="vi"&gt;@category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:image&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
        &lt;span class="n"&gt;uploaded_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Cloudinary&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Uploader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:image&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="vi"&gt;@image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="n"&gt;uploaded_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;event_id: &lt;/span&gt;&lt;span class="vi"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; 

      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;event: &lt;/span&gt;&lt;span class="no"&gt;EventSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;category: &lt;/span&gt;&lt;span class="no"&gt;CategorySerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :created&lt;/span&gt;  
    &lt;span class="k"&gt;else&lt;/span&gt; 
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="s1"&gt;'Failed to create Event.'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :not_acceptable&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I had many &lt;code&gt;byebug&lt;/code&gt; exercises on &lt;code&gt;create&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; actions in &lt;code&gt;Api::V1::EventsController&lt;/code&gt;. Not only a new &lt;code&gt;event&lt;/code&gt; will be created, but also its respective &lt;code&gt;category&lt;/code&gt; and &lt;code&gt;image&lt;/code&gt;. I have an event entry form on my front-end to accommodate user inputs. I utilize &lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; in order to manipulate images with a URL-based API. The rest of my controllers' actions are mostly &lt;code&gt;index&lt;/code&gt; and &lt;code&gt;show&lt;/code&gt;. This is where &lt;a href="https://github.com/rails-api/active_model_serializers" rel="noopener noreferrer"&gt;Active Model Serializers&lt;/a&gt; helps with displaying any intended attributes to pass information necessary over to front-end's Redux state management. Including model relationships helps to display arrays of event's category and image in one single &lt;em&gt;Object&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EventSerializer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Serializer&lt;/span&gt;
  &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:date_strftime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:time_strftime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:vibe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;

  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:category&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
  &lt;span class="n"&gt;has_one&lt;/span&gt; &lt;span class="ss"&gt;:image&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I believe that's all I have for my back-end! I have attached my GitHub repo below.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit" rel="noopener noreferrer"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/Storybook_backend" rel="noopener noreferrer"&gt;
        Storybook_backend
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Minimum Viable Product (MVP) of Storybook app is to allow the user to log events, places, moods and self-reflect from various points of views (calendar, map, photos).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Storybook&lt;/h1&gt;
&lt;/div&gt;

&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_backendpublic/images/back_end.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_backendpublic%2Fimages%2Fback_end.gif"&gt;&lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Domain Modeling :: Digital Journaling&lt;/strong&gt;&lt;br&gt;
Welcome to my simplistic version of digital journaling app.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/fentybit/Storybook_frontend" rel="noopener noreferrer"&gt;Front-End GitHub Repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/vlcJ1QT3M_M" rel="nofollow noopener noreferrer"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/storybook-4p2g" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;I have been a long-advocate for having meaningful connection through self-reflection. While some journal apps I have seen simply record special memories and events, some focus more on mental health, mindfulness and self-care. I have decided to approach this app build with basic features of recorded events and necessary attributes. &lt;/p&gt;
&lt;p&gt;The Minimum Viable Product (MVP) of Storybook app is to allow the user to log events, places, moods and self-reflect from various points of views (calendar, map, photos).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_backendpublic/images/wireframe.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_backendpublic%2Fimages%2Fwireframe.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_backendpublic/images/erd_present.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_backendpublic%2Fimages%2Ferd_present.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_backendpublic/images/components.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_backendpublic%2Fimages%2Fcomponents.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Models&lt;/strong&gt; &lt;br&gt;
User, Event, Category, Image&lt;br&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;user &lt;code&gt;has_many&lt;/code&gt; :events&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;event &lt;code&gt;belongs_to&lt;/code&gt; :user&lt;br&gt;
event &lt;code&gt;belongs_to&lt;/code&gt; :category&lt;br&gt;
event &lt;code&gt;has_many&lt;/code&gt; :images&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;category &lt;code&gt;has_many&lt;/code&gt; :events&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;image &lt;code&gt;belongs_to&lt;/code&gt; :event&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; &lt;br&gt;
ApplicationController&lt;br&gt;
Api::V1::AuthController&lt;br&gt;
Api::V1::CategoriesController&lt;br&gt;
Api::V1::EventsController&lt;br&gt;
Api::V1::ImagesController&lt;br&gt;
Api::V1::UsersController&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User Account and Validation&lt;/strong&gt; &lt;br&gt;
JWT Authentication: Sign Up, Log In and Log Out.&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Database&lt;/h2&gt;

&lt;/div&gt;
&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 &lt;a href="https://console.cloud.google.com/apis/dashboard" rel="nofollow noopener noreferrer"&gt;Google Developer API&lt;/a&gt;
&lt;/li&gt;
&lt;li class="task-list-item"&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/Storybook_backend" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h4&gt;
  
  
  4. React — Getting Started &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;I started with &lt;code&gt;npx create-react-app storybook&lt;/code&gt; and &lt;code&gt;npm install redux &amp;amp;&amp;amp; npm install react-redux&lt;/code&gt; as for Redux state management. I learned that NPM packages do not allow upper case characters because unix filesystems are case-sensitive (as I previously tried &lt;code&gt;Storybook&lt;/code&gt;, and 🤨  it failed). For whatever reason, I froze for quite sometime, not knowing where to get a start with my React app. I have decided to step back and brainstorm a file structuring diagram, which helped tremendously as I progressed through my code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmlv102x3y7fynqwjg6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmlv102x3y7fynqwjg6w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started with my &lt;code&gt;index.js&lt;/code&gt; file, and set up my &lt;code&gt;Provider&lt;/code&gt; and &lt;code&gt;store&lt;/code&gt;. Following &lt;a href="https://www.freecodecamp.org/news/a-better-way-to-structure-react-projects/" rel="noopener noreferrer"&gt;best practice&lt;/a&gt;, I kept &lt;code&gt;actions&lt;/code&gt;, &lt;code&gt;reducers&lt;/code&gt; and &lt;code&gt;store.js&lt;/code&gt; inside of the &lt;code&gt;Redux&lt;/code&gt; folder. The &lt;code&gt;App.js&lt;/code&gt; carries the first parent container for my &lt;code&gt;ProfileContainer&lt;/code&gt;. This component becomes a portal once a user successfully signs in, and it will navigate the user to 3 &lt;em&gt;container components&lt;/em&gt;, &lt;code&gt;NavBar&lt;/code&gt;, &lt;code&gt;EventViewList&lt;/code&gt; and &lt;code&gt;DisplayContainer&lt;/code&gt;. The rests are &lt;em&gt;presentational components&lt;/em&gt; and most of them are built as functional components which rely mainly on &lt;em&gt;props&lt;/em&gt;. With all that said, I definitely spent a good chunk of time with file-naming, aligning file structures and folder hierarchy. On another note, &lt;a href="https://github.com/zalmoxisus/redux-devtools-extension" rel="noopener noreferrer"&gt;Redux DevTools&lt;/a&gt; is a great tool that I set up in order to view Redux state.&lt;/p&gt;




&lt;h4&gt;
  
  
  5. &lt;code&gt;Action&lt;/code&gt; → &lt;code&gt;Reducer&lt;/code&gt; → &lt;code&gt;New State&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;connect()&lt;/code&gt; and &lt;code&gt;Provider&lt;/code&gt; play a big role as part of &lt;strong&gt;React Redux&lt;/strong&gt; middleware. &lt;code&gt;Provider&lt;/code&gt; ensures that my React app can access data from the store, and &lt;code&gt;connect()&lt;/code&gt; allows whichever component to specify which state and actions the app needs access to. I implemented &lt;code&gt;combineReducers&lt;/code&gt; to consolidate all reducers and set the Redux state management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://your-storybook.herokuapp.com/api/v1/events/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;eventId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET_EVENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One example of my actions would be the &lt;code&gt;fetchEvent(eventId)&lt;/code&gt; that asynchronously fetches my back-end route, and &lt;code&gt;dispatch&lt;/code&gt; a reducer to return a value.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;eventReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET_EVENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;eventReducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I should be able to access the object value of &lt;code&gt;event&lt;/code&gt; with &lt;code&gt;mapStateToProps&lt;/code&gt; in any desirable component to display the current state of event entry. I have a total of 8 reducers from category, error, user, token and others under one &lt;code&gt;rootReducer&lt;/code&gt;.&lt;/p&gt;


&lt;h4&gt;
  
  
  6. Nested Routes in React Router &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;ReactJS relies upon &lt;strong&gt;Client-Side&lt;/strong&gt; routing to handle routing, fetching and displaying data in the browser. It is after all a &lt;strong&gt;Single-Page Application (SPA)&lt;/strong&gt;. While it benefits in speed, it also presents more design challenges. I tried my best to achieve proper RESTful routing.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;EventViewList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;align&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Switch&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/calendar/:eventId`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteCalendar&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;withMultipleDates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calendar&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;interpolateSelection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;defaultMultipleDateInterpolation&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onSelect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;renderSelectedEventDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedDatesArray&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/calendar`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteCalendar&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;withMultipleDates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calendar&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;interpolateSelection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;defaultMultipleDateInterpolation&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onSelect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;renderSelectedEventDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedDatesArray&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/map/:eventId`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MapView&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/map`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MapView&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/newentry`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteCalendar&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/photos/:eventId`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotosView&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/photos`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotosView&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/:categoryId/:eventId/edit`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CalendarView&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/:categoryId/:eventId`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CalendarView&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/:categoryId`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CalendarView&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;routerProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteCalendar&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Switch&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;EventViewList&lt;/code&gt; component is my middle presentational component that displays various UI components in correspond to the left navigation bar. I would refer my &lt;code&gt;EventViewList&lt;/code&gt; as an intermediary. As the user navigates through, my right presentational component, &lt;code&gt;EventDisplay&lt;/code&gt;, will exhibit detailed information. Snippet below represents Route path &lt;code&gt;${url}/calendar/:eventId&lt;/code&gt; where &lt;code&gt;calendar&lt;/code&gt; view displays propagated entry dates the user had previously recorded, and &lt;code&gt;eventId&lt;/code&gt; will fetch the associated event entry from provided &lt;code&gt;events&lt;/code&gt; state from Redux store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79soe9jveukwo7j7ud6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79soe9jveukwo7j7ud6p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h4&gt;
  
  
  7. Google Maps Platform APIs &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;I have decided to utilize &lt;a href="https://www.npmjs.com/package/google-maps-react" rel="noopener noreferrer"&gt;google-maps-react&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/react-google-autocomplete" rel="noopener noreferrer"&gt;react-google-autocomplete&lt;/a&gt; NPM packages. Their documentation is pretty solid and provides a straightforward code implementation to my Storybook MVP needs. API can be retrieved from Google Developers Console, and I include Geocoding API, Maps JavaScript API and Places API. Once &lt;code&gt;GoogleApiWrapper&lt;/code&gt; from &lt;code&gt;'google-maps-react'&lt;/code&gt; and &lt;code&gt;PlacesAutocomplete&lt;/code&gt;  from &lt;code&gt;'react-places-autocomplete'&lt;/code&gt; are imported to my &lt;code&gt;Form&lt;/code&gt; component, the user can automatically submit an address and/or location from the autocomplete textfield. It should automatically send an API request to retrieve the location's latitude and longitude. Each location and its respective coordinates will be saved in the PostgreSQL database, and that's how I was able to collect an array of various coordinates and propagate them to a map view. I also learned how to save an API_KEY by adding &lt;code&gt;REACT_APP_&lt;/code&gt; to my API key in the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4a7i4ts46fqtuq78q7d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4a7i4ts46fqtuq78q7d.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h4&gt;
  
  
  8. Material-UI and Lessons Learned &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;I had much fun perusing through &lt;a href="https://material-ui.com/" rel="noopener noreferrer"&gt;Material-UI&lt;/a&gt; library. If given more time, I would love to develop Storybook mobile UI. Current project build is focused on browser desktop UI. There are a lot of customization theming that piques my design interest. &lt;/p&gt;

&lt;p&gt;Anyhow... I am glad I had the chance to learn ReactJS/Redux, and it definitely &lt;a href="https://gist.github.com/tkrotoff/b1caa4c3a185629299ec234d2314e190" rel="noopener noreferrer"&gt;speaks on its own popularity and demand&lt;/a&gt;. React provides a modular way to separate code and functionality in &lt;em&gt;declarative writing&lt;/em&gt; structure, producing highly reusable and independent entities. I now feel comfortable with JSX syntax, container vs. presentational components, Redux state management, Client Routing and finally, implementing Google Maps API. Check out my GitHub repo!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit" rel="noopener noreferrer"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/Storybook_frontend" rel="noopener noreferrer"&gt;
        Storybook_frontend
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Minimum Viable Product (MVP) of Storybook app is to allow user to log events, places, moods and self-reflect from various points of views (calendar, map, photos).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Storybook&lt;/h1&gt;
&lt;/div&gt;

&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_frontendimages/main.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_frontendimages%2Fmain.gif"&gt;&lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Domain Modeling :: Digital Journaling&lt;/strong&gt;&lt;br&gt;
Welcome to my simplistic version of digital journaling app.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/fentybit/Storybook_backend" rel="noopener noreferrer"&gt;Back-End GitHub Repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/vlcJ1QT3M_M" rel="nofollow noopener noreferrer"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/storybook-4p2g" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;I have been a long-advocate for having meaningful connection through self-reflection. While some journal apps I have seen simply record special memories and events, some focus more on mental health, mindfulness and self-care. I have decided to approach this app build with basic features of recorded events and necessary attributes. &lt;/p&gt;
&lt;p&gt;The Minimum Viable Product (MVP) of Storybook app is to allow the user to log events, places, moods and self-reflect from various points of views (calendar, map, photos).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_frontendimages/wireframe.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_frontendimages%2Fwireframe.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_frontendimages/erd_present.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_frontendimages%2Ferd_present.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/Storybook_frontendimages/components.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FStorybook_frontendimages%2Fcomponents.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Models&lt;/strong&gt; &lt;br&gt;
User, Event, Category, Image&lt;br&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;user &lt;code&gt;has_many&lt;/code&gt; :events&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;event &lt;code&gt;belongs_to&lt;/code&gt; :user&lt;br&gt;
event &lt;code&gt;belongs_to&lt;/code&gt; :category&lt;br&gt;
event &lt;code&gt;has_many&lt;/code&gt; :images&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;category &lt;code&gt;has_many&lt;/code&gt; :events&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;image &lt;code&gt;belongs_to&lt;/code&gt; :event&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; &lt;br&gt;
ApplicationController&lt;br&gt;
Api::V1::AuthController&lt;br&gt;
Api::V1::CategoriesController&lt;br&gt;
Api::V1::EventsController&lt;br&gt;
Api::V1::ImagesController&lt;br&gt;
Api::V1::UsersController&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User Account and Validation&lt;/strong&gt; &lt;br&gt;
JWT Authentication: Sign Up, Log In and Log Out.&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Database&lt;/h2&gt;

&lt;/div&gt;
&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 &lt;a href="https://console.cloud.google.com/apis/dashboard" rel="nofollow noopener noreferrer"&gt;Google Developer API&lt;/a&gt;
&lt;/li&gt;
&lt;li class="task-list-item"&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/Storybook_frontend" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6o8a8jphtni302slpng.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6o8a8jphtni302slpng.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  9. Build Status and Future Improvement &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Storybook was completed in a 2-week timeframe from implementing Rails back-end, ReactJS front-end, Cloudinary API, Google Maps API and Material-UI library. I have several ideas as I progressed through building my MVP (Minimum Viable Product). Future cycle of product development as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search Bar. Over the time, the user will have many events, and it gets troublesome when the user needs to immediately access a specific event entry. A search bar to quickly type event title and access the journal entry would be useful.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;Friend&lt;/code&gt; to model associations. I envision my app to emulate similar concept such as Instagram. Instead of creating a simple journaling app, what about a social journaling platform. Each user can personalize their privacy whether or not they'd like to share with their friends. &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfajn4d8bpaqt174xej0.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;Adding mood tracker. Current attribute &lt;code&gt;vibe&lt;/code&gt; to capture my preliminary attempt of gathering user mood data on each event entry. I found a &lt;a href="https://github.com/drypycode/MoodTracker-API" rel="noopener noreferrer"&gt;mood tracker API&lt;/a&gt; that I would love to integrate in future project build. User can view their journal entries based on &lt;code&gt;Mood&lt;/code&gt; under View NavBar.&lt;/li&gt;
&lt;li&gt;Current event entry only allows one image upload. User should be able to upload multiple images, insert GIF and video upload.&lt;/li&gt;
&lt;li&gt;Create a toggle track for dark mode. 😎&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Post Scriptum:&lt;br&gt;
This is my Module 5 capstone project with Flatiron School. I believe one of the catalyst to becoming a good programmer is to welcome constructive criticism. Feel free to drop a message. 🙂&lt;/p&gt;

&lt;p&gt;Keep Calm, and Code On.&lt;/p&gt;

&lt;p&gt;External Sources:&lt;br&gt;
&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;ReactJS Documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/google-maps-react" rel="noopener noreferrer"&gt;Google Maps React&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/react-google-autocomplete" rel="noopener noreferrer"&gt;React Google Autocomplete&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/clauderic/react-infinite-calendar" rel="noopener noreferrer"&gt;React Infinite Calendar&lt;/a&gt;&lt;br&gt;
&lt;a href="https://material-ui.com/" rel="noopener noreferrer"&gt;Material-UI&lt;/a&gt;&lt;br&gt;
&lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;center&gt;[**fentybit**](https://fentybit.me/) | [GitHub](https://github.com/fentybit) | [Twitter](https://twitter.com/fentybit) | [LinkedIn](https://www.linkedin.com/in/fentybit/)&lt;/center&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>googlecloud</category>
      <category>javascript</category>
    </item>
    <item>
      <title>My First Personal Site! 📣</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Wed, 14 Apr 2021 20:23:29 +0000</pubDate>
      <link>https://forem.com/fentybit/my-first-personal-site-4m20</link>
      <guid>https://forem.com/fentybit/my-first-personal-site-4m20</guid>
      <description>&lt;p&gt;I can not believe that I have 2 months left with Flatiron School, and hopefully by then I can officially call myself a Full-Stack Software Engineer. 👩🏻‍💻&lt;/p&gt;

&lt;p&gt;Aside from revamping my resume, I have been working on building my personal site. After weeks of debating if I should be building from scratch or not, I decided to deploy my first portfolio site from a ready-made HTML5 template. I can always refine my portfolio site later as I develop more skills, and eventually design my own UI components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Starting Point&lt;/strong&gt;&lt;br&gt;
Not sure where to start, I looked for advice from &lt;a href="https://www.freecodecamp.org/" rel="noopener noreferrer"&gt;freeCodeCamp&lt;/a&gt;. I found this tutorial of &lt;a href="https://www.freecodecamp.org/news/how-to-put-a-website-online-guide-to-website-creation-custom-domain-and-hosting/" rel="noopener noreferrer"&gt;How to Put a Website Online&lt;/a&gt;, and it was extremely useful in providing guidance for someone (like me) who has no knowledge on buying a custom domain, hosting and outsourcing a template. I had fun perusing through &lt;a href="https://pixelarity.com/" rel="noopener noreferrer"&gt;Pixelarity&lt;/a&gt; where you can browse HTML responsive template designs. Basic skills required include HTML, CSS and JavaScript. The next step was trying to figure out my custom domain. Funny thing, this effort frustrates me the most, and I could not make up my mind. Long story short, I ended up re-branding myself to &lt;code&gt;@fentybit&lt;/code&gt;, and settled on &lt;code&gt;fentybit.me&lt;/code&gt;. I love numbers, and hence, &lt;code&gt;bit&lt;/code&gt; or binary digit. Then, I mulled over &lt;code&gt;.dev&lt;/code&gt; and &lt;code&gt;.me&lt;/code&gt; for quite some time. I learned from &lt;a href="https://medium.engineering/use-a-dev-domain-not-anymore-95219778e6fd" rel="noopener noreferrer"&gt;other developers and their thoughts on &lt;code&gt;.dev&lt;/code&gt; domain&lt;/a&gt;, and I settled on &lt;code&gt;.me&lt;/code&gt;. I want my site to personally share who I am and what I am, in the most minimalistic way. I am glad the custom domain was still available. Thank you &lt;a href="https://www.namecheap.com/" rel="noopener noreferrer"&gt;Namecheap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personalize your Site&lt;/strong&gt;&lt;br&gt;
Personalizing HTML/CSS attributes and content delivery took most of my time, but Pixelarity made it so effortless! If there is anything new, it would be trying to link my &lt;em&gt;contact&lt;/em&gt; page so other devs can communicate back to me. &lt;a href="https://formspree.io/" rel="noopener noreferrer"&gt;Formspree&lt;/a&gt; provides this service. I only need to submit their API to my front-end code, and they take care of the rest. 📝&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyz6oc4rpamiruhamt97i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyz6oc4rpamiruhamt97i.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Namecheap &amp;amp;&amp;amp; Netlify&lt;/strong&gt;&lt;br&gt;
While there are a lot of hosting providers such as Bluehost, GoDaddy, Hostinger, DreamHost and so on, you can always get free ones from either &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub pages&lt;/a&gt;. I had success initially deploying with GitHub pages, though my site resulted being &lt;em&gt;"Not Secure"&lt;/em&gt; on Chrome. I made another attempt on setting up my domain with Namecheap and Netlify. Starting with Namecheap to configure the DNS settings &amp;gt; &lt;strong&gt;Manage&lt;/strong&gt;. Under &lt;strong&gt;Nameservers&lt;/strong&gt; category, I had to update from &lt;strong&gt;Namecheap Basic DNS&lt;/strong&gt; to &lt;strong&gt;Custom DNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbasafc7bgbiyv96h7u0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbasafc7bgbiyv96h7u0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reroute to my Netlify &lt;strong&gt;Domain Settings&lt;/strong&gt; real quick to add my custom domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgf0yapfw5jd1dzwousp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgf0yapfw5jd1dzwousp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step would be to select &lt;strong&gt;Set Up Netlify DNS&lt;/strong&gt;. I would need to acquire &lt;em&gt;a list of Nameservers&lt;/em&gt; from Netlify and propagate on Namecheap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8x96iw8bteezclbka10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8x96iw8bteezclbka10.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy all of &lt;em&gt;Netlify's DNS servers&lt;/em&gt; to &lt;em&gt;Namecheap Nameservers&lt;/em&gt;, and click the green check button to save this setting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tj4o3183cdp9kbnf8it.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tj4o3183cdp9kbnf8it.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I was not able to figure out the SSL/TLS certificate with GitHub pages, I learned Netlify will provision &lt;em&gt;Let's Encrypt&lt;/em&gt; certificate automatically once the DNS configuration on the custom domain pointing to Netlify's servers. Namecheap suggests revisiting your site in 24 - 48 hours once Netlify's DNS fully propagated.&lt;/p&gt;




&lt;p&gt;It's official. Now I have a personal site! 💥&lt;br&gt;
Check out &lt;a href="https://fentybit.me/" rel="noopener noreferrer"&gt;https://fentybit.me/&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmk0orhrf4jcdap26s9x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmk0orhrf4jcdap26s9x.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;center&gt;[**fentybit**](https://fentybit.me/) | [GitHub](https://github.com/fentybit) | [Twitter](https://twitter.com/fentybit) | [LinkedIn](https://www.linkedin.com/in/fentybit/)&lt;/center&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Deploy Rails API on Heroku and Vanilla JavaScript on Netlify</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sat, 03 Apr 2021 19:54:35 +0000</pubDate>
      <link>https://forem.com/fentybit/deploy-rails-api-on-heroku-and-vanilla-javascript-on-netlify-1c24</link>
      <guid>https://forem.com/fentybit/deploy-rails-api-on-heroku-and-vanilla-javascript-on-netlify-1c24</guid>
      <description>&lt;p&gt;This blog is part II of my Project Deployment series. This is my second attempt to deploy my recent project, &lt;a href="https://dev.to/fentybit/know-it-all-2kpp"&gt;Know It All&lt;/a&gt;. 🚀  The project was created with &lt;strong&gt;Rails API back-end&lt;/strong&gt; and &lt;strong&gt;JavaScript/HTML/CSS front-end&lt;/strong&gt;. I chose to deploy my back-end on &lt;a href="https://www.heroku.com/"&gt;Heroku&lt;/a&gt;, and my front-end on &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Deploy Rails API on Heroku&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since I already signed up previously on &lt;a href="https://signup.heroku.com/"&gt;Heroku&lt;/a&gt;, I had to log in and create this new project.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--utRIc87N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cwle6vhy6m8psp4q07n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--utRIc87N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cwle6vhy6m8psp4q07n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had to set &lt;code&gt;lets-know-it-all&lt;/code&gt; as &lt;code&gt;know-it-all&lt;/code&gt; app domain name was already taken. 🥲&lt;/p&gt;

&lt;p&gt;My deployment would be performed with &lt;a href="https://devcenter.heroku.com/articles/heroku-cli#download-and-install"&gt;Heroku CLI&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ heroku login
  › Warning: Our terms of service have changed: https://dashboard.heroku.com/terms-of-service
  heroku: Press any key to open up the browser to login or q to exit: 
  Opening browser to https://cli-auth.heroku.com/auth/cli/browser/....
  Logging in... done
  Logged in as _______@gmail.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I built the project already with PostgreSQL, unlike my previous Ruby on Rails project which I had to migrate my SQLite to PostgreSQL database. Make sure you are utilizing gem &lt;code&gt;pg&lt;/code&gt;. Since I used Ruby version 2.6.1, I had to use &lt;a href="https://devcenter.heroku.com/articles/heroku-18-stack"&gt;Heroku-18&lt;/a&gt; stack. You may review this &lt;a href="https://devcenter.heroku.com/categories/stacks"&gt;Heroku stacks&lt;/a&gt; documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ Bundler Output: Your bundle only supports platforms ["x86_64-darwin-19"] but your local platform
  is x86_64-linux. Add the current platform to the lockfile with `bundle lock
  --add-platform x86_64-linux` and try again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heroku CLI is very friendly, and it will provide you guidance if any. Following Heroku's instruction on command prompt &lt;code&gt;bundle lock --add-platform x86_64-linux&lt;/code&gt;, it immediately took care of my bundling issue. The following two commands &lt;code&gt;heroku create --stack heroku-18&lt;/code&gt;, and &lt;code&gt;$ git push heroku master&lt;/code&gt; kicked off my project deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pdspQgnm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/km0osyppiant6tjc2yfe.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pdspQgnm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/km0osyppiant6tjc2yfe.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's not forget that once Heroku app is successfully created, the database should be migrated to Heroku's PostgreSQL. If you have seeding content in your &lt;code&gt;seeds.rb&lt;/code&gt; file, then it is also prudent to run &lt;code&gt;heroku run rails db:seed&lt;/code&gt;. &lt;em&gt;Note — I had to reset my deployment a few times as I was trying to debug a few error codes in my &lt;code&gt;seeds.rb&lt;/code&gt;. &lt;code&gt;heroku pg:reset DATABASE&lt;/code&gt; comes in handy whenever you need to reset your Heroku PostgreSQL.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ heroku run rails db:migrate
$ heroku run rails db:seed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---syVjCIs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvv8kojc1tzkvqywituz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---syVjCIs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvv8kojc1tzkvqywituz.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I have my &lt;a href="https://lets-know-it-all.herokuapp.com/api/v1/categories"&gt;Rails API set up with Heroku&lt;/a&gt;, sweet!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ldWm4GXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv1bwjrpla5uggw4fw27.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ldWm4GXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv1bwjrpla5uggw4fw27.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Deploy Vanilla JavaScript on Netlify&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This would be my first time deploying anything with &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;! and it was super easy. 🥳&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8KA9HYsu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cumky486ytjvvnxm6hde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8KA9HYsu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cumky486ytjvvnxm6hde.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have a tendency to use GitHub as my third-party authentication when signing up either on Heroku or Netlify. Select &lt;strong&gt;New site from Git&lt;/strong&gt; to link your GitHub repo. I separated my front-end and back-end repo for this purpose, so I could simply link my &lt;a href="https://github.com/fentybit/KnowItAll_frontend"&gt;KnowItAll_frontend&lt;/a&gt; repo to Netlify. It should only take less than a minute to deploy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Eisbz_xb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oo6ghn5pqf0vad3ent5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Eisbz_xb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oo6ghn5pqf0vad3ent5i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out my simple Trivia app, &lt;a href="https://lets-know-it-all.netlify.app/"&gt;Know It All&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-ZUH5a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1phsb6kae0fpvgsxqrm0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-ZUH5a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1phsb6kae0fpvgsxqrm0.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>heroku</category>
      <category>netlify</category>
      <category>rails</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Know It All </title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sun, 14 Mar 2021 16:09:56 +0000</pubDate>
      <link>https://forem.com/fentybit/know-it-all-2kpp</link>
      <guid>https://forem.com/fentybit/know-it-all-2kpp</guid>
      <description>&lt;p&gt;Happy Spring, fellow developers! &lt;/p&gt;

&lt;p&gt;Since my recent Ruby on Rails project on &lt;a href="https://dev.to/codinghall/plan-my-md-visit-c0l"&gt;Plan My MD Visit&lt;/a&gt;, I have immersed myself in JavaScript Fundamentals from recognizing JavaScript events, DOM manipulation, ES6 Syntax Sugar and introduction of Object-Orientation. I plan to supplement my JavaScript learning materials after this project submission. &lt;/p&gt;

&lt;p&gt;I went through a few iterations in my head on &lt;a href="https://en.wikipedia.org/wiki/Single-page_application" rel="noopener noreferrer"&gt;Single-Page Application (&lt;strong&gt;SPA&lt;/strong&gt;)&lt;/a&gt; prior to settling on an idea. Overthinking as usual, but in my defense it is one &lt;code&gt;HTML&lt;/code&gt; file, and lends itself too much freedom. 😅  Moving on, my husband loves trivia, and nothing is better than to surprise him by creating my own version of a trivia app, &lt;strong&gt;Know It All&lt;/strong&gt;. The challenge becomes finding a completely free JSON API for use. This capstone project focuses on creating &lt;strong&gt;Ruby on Rails&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;back-end&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;JavaScript/HTML/CSS&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;front-end&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Back-End Development
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Planning and Building Rails API&lt;/li&gt;
&lt;li&gt;Open Trivia DB API&lt;/li&gt;
&lt;li&gt;Generating Active Record Models&lt;/li&gt;
&lt;li&gt;Routes, Controllers and Serializers&lt;/li&gt;
&lt;li&gt;Communicating with the Server&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Front-End Web Programming
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;DOM Manipulation with JavaScript Event Listeners&lt;/li&gt;
&lt;li&gt;Re-factoring Early&lt;/li&gt;
&lt;li&gt;End Page Sequence&lt;/li&gt;
&lt;li&gt;Lessons Learned&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Build Status and Future Improvement
&lt;/h4&gt;




&lt;h3&gt;
  
  
  Back-End Development
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Planning and Building Rails API &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;--api&lt;/code&gt;, Rails removes a lot of default features and middleware, and our controllers by default inherit from &lt;code&gt;ActionController::API&lt;/code&gt;. This differs slightly from traditional &lt;em&gt;Ruby on Rails&lt;/em&gt; application. In my previous &lt;em&gt;RoR&lt;/em&gt; project, I had my controllers inheriting from &lt;code&gt;ActionController::Base&lt;/code&gt; with responsibilities in creating routes and rendering many &lt;code&gt;_.html.erb&lt;/code&gt; files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new know_it_all_backend --database=postgresql --api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above command will generate a Rails API using &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; database. The intent is to deploy my backend application eventually on &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;, which does not support &lt;a href="https://sqlitebrowser.org/" rel="noopener noreferrer"&gt;SQLite&lt;/a&gt; database. One more important thing to add is to &lt;code&gt;bundle install&lt;/code&gt; gem &lt;code&gt;rack-cors&lt;/code&gt;. This is useful for handling &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;Cross-Origin Resource Sharing (CORS)&lt;/a&gt;&lt;/strong&gt; configuration, allowing my front-end application to perform asynchronous requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusi3l1qc4b1hp02ofm9r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusi3l1qc4b1hp02ofm9r.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I approached this project in a &lt;em&gt;vertical manner&lt;/em&gt;, building out one model and/or feature at a time. This strategy streamlines any effort when dealing with complex relationships from back-end to front-end, and vice versa.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Open Trivia DB API &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;After traversing through the API universe, I got excited when finding an &lt;a href="https://opentdb.com/" rel="noopener noreferrer"&gt;Open Trivia Database&lt;/a&gt; without the need for an API Key. Awesome sauce. 🙅🏻‍♀️ &lt;/p&gt;

&lt;p&gt;The challenge is less on acquiring the JSON API, but setting up the &lt;code&gt;Api&lt;/code&gt; adapter class on Rails back-end. I utilized the &lt;code&gt;.shuffle&lt;/code&gt; Ruby method to randomize the provided multiple choice. In the JavaScript front-end, I should be able to set up &lt;code&gt;if/else&lt;/code&gt; conditionals when comparing the user's selected answer to the &lt;code&gt;correct_answer&lt;/code&gt;. I managed to &lt;code&gt;JSON.parse&lt;/code&gt; in &lt;code&gt;irb&lt;/code&gt;, and confirmed responses back from the open/free API.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"category"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Animals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"multiple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"difficulty"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"hard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"question"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"What was the name of the Ethiopian Wolf before they knew it was related to wolves?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"correct_answer"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Simien Jackel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"incorrect_answers"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Ethiopian Coyote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="s2"&gt;"Amharic Fox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Canis Simiensis"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"correct_answer"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"incorrect_answers"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"incorrect_answers"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"incorrect_answers"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;shuffle&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Amharic Fox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Canis Simiensis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Simien Jackel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Ethiopian Coyote"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple_choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Amharic Fox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Canis Simiensis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Simien Jackel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Ethiopian Coyote"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple_choice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Amharic Fox"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple_choice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Canis Simiensis"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple_choice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Simien Jackel"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple_choice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Ethiopian Coyote"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There will be a total of eight (8) Trivia categories: Animals, Celebrities, Computer Science, Geography, History, Mathematics, Music and Sports. Once the &lt;code&gt;Api&lt;/code&gt; adapter class was fully set up, I initiated the creation of both &lt;code&gt;Category&lt;/code&gt; and &lt;code&gt;Question&lt;/code&gt; models in the &lt;code&gt;seeds.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3rm7b3qq9zutzwjervx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3rm7b3qq9zutzwjervx.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Generating Active Record Models &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rails g model User name avatar animals_score:integer celebrities_score:integer computer_science_score:integer geography_score:integer history_score:integer mathematics_score:integer music_score:integer sports_score:integer 
    invoke  active_record
    create    db/migrate/20210224154513_create_users.rb
    create    app/models/user.rb

$ rails g model Category name 
    invoke  active_record
    create    db/migrate/20210224045712_create_categories.rb
    create    app/models/category.rb

$ rails g model Question category_id:integer question:text choice1 choice2 choice3 choice4 answer
    invoke  active_record
    create    db/migrate/20210227220035_create_questions.rb
    create    app/models/question.rb

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the terminal, I can now run &lt;code&gt;rails db:create &amp;amp;&amp;amp; rails db:migrate&lt;/code&gt;. The &lt;code&gt;rails db:create&lt;/code&gt; is necessary for PostgreSQL database. At first, I had an erroneous terminal return, and had to update my PostgreSQL 13. Once re-installed and 🐘  running, the command should create the database and run migration swiftly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rails db:create &amp;amp;&amp;amp; rails db:migrate
  Created database 'know_it_all_backend_development'
  Created database 'know_it_all_backend_test'
  == 20210224045712 CreateCategories: migrating =================================
  -- create_table(:categories)
     -&amp;gt; 0.0545s
  == 20210224045712 CreateCategories: migrated (0.0547s) ========================

  == 20210224154513 CreateUsers: migrating ======================================
  -- create_table(:users)
     -&amp;gt; 0.0575s
  == 20210224154513 CreateUsers: migrated (0.0575s) =============================

  == 20210227220035 CreateQuestions: migrating ==================================
  -- create_table(:questions)
     -&amp;gt; 0.0571s
  == 20210227220035 CreateQuestions: migrated (0.0572s) =========================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The next step would be to test my models and associations. My association between &lt;code&gt;Category&lt;/code&gt; and &lt;code&gt;Question&lt;/code&gt; would be as simple as category &lt;code&gt;has_many&lt;/code&gt; questions, and a question &lt;code&gt;belongs_to&lt;/code&gt; a category.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8d46wqrriy41txad7of.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8d46wqrriy41txad7of.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:questions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Question&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:category&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;dependent: :destroy&lt;/code&gt; would be helpful for &lt;code&gt;.destroy_all&lt;/code&gt; method in &lt;code&gt;seeds.rb&lt;/code&gt; file. This is useful when triggering the &lt;code&gt;rails db:seed&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;As an &lt;a href="https://guides.rubyonrails.org/association_basics.html" rel="noopener noreferrer"&gt;Active Record&lt;/a&gt; veteran, it is still a good practice to validate every single instance of  association relationships. &lt;em&gt;Note — presented model attributes resulted from extensive trial and error. I approached this project with one feature working simultaneously on the back-end and front-end, adding one model attribute at a time.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;001 &amp;gt; animals = Category.create(name: "Animals")
  (0.2ms) BEGIN
  Category Create (4.8ms)  INSERT INTO "categories" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "Animals"], ["created_at", "2021-02-28 18:30:29.016555"], ["updated_at", "2021-02-28 18:30:29.016555"]]
  (40.4ms)  COMMIT
  =&amp;gt; #&amp;lt;Category id: 1, name: "Animals", created_at: "2021-02-28 18:30:29", updated_at: "2021-02-28 18:30:29"&amp;gt;
002 &amp;gt; animals_trivia = animals.questions.create(JSON.parse(File.read("animals.json")))
  (0.2ms) BEGIN
  Category Create (4.8ms)  INSERT INTO "categories" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "Animals"], ["created_at", "2021-02-28 18:30:29.016555"], ["updated_at", "2021-02-28 18:30:29.016555"]]
  (40.4ms)  COMMIT
  =&amp;gt; #&amp;lt;Category id: 1, name: "Animals", created_at: "2021-02-28 18:30:29", updated_at: "2021-02-28 18:30:29"&amp;gt; 
  (0.3ms) BEGIN
  Question Create (4.8ms)  INSERT INTO "questions" ("question", "choice1", "choice2", "choice3", "choice4", "answer", "category_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id"  [["question", "What was the name of the Ethiopian Wolf before they knew it was related to wolves?"], ["choice1", "Canis Simiensis"], ["choice2", "Simien Jackel"], ["choice3", "Ethiopian Coyote"], ["choice4", "Amharic Fox"], ["answer", "Simien Jackel"], ["category_id", 1], ["created_at", "2021-02-28 18:30:42.398662"], ["updated_at", "2021-02-28 18:30:42.398662"]]
  (55.1ms)  COMMIT
  (0.2ms) BEGIN
  ...
003 &amp;gt; animals_trivia.all.count
  =&amp;gt; 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  4. Routes, Controllers and Serializers &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;h5&gt;
  
  
  Routes
&lt;/h5&gt;

&lt;p&gt;With the front-end application hosted on a specific domain, I would think it is prudent to &lt;em&gt;namespace&lt;/em&gt; my back-end routes. It provides an indication that these back-end routes are associated with the API. For example, &lt;code&gt;https://knowitall.com/api/v1/categories&lt;/code&gt;. The &lt;code&gt;api/v1&lt;/code&gt; suggests my Rails API &lt;em&gt;version 1&lt;/em&gt;. I might return and continue my effort on future build status (&lt;em&gt;version 2&lt;/em&gt;, etc). In the &lt;code&gt;config/routes.rb&lt;/code&gt;, I provided the intended &lt;em&gt;namespaced&lt;/em&gt; routes and confirmed with &lt;code&gt;rails routes&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 

  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:v1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
        &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:questions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  Controllers
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;rails g controller api/Users&lt;/code&gt;, &lt;code&gt;rails g controller api/v1/Questions&lt;/code&gt; and &lt;code&gt;rails g controller api/v1/Categories&lt;/code&gt; create &lt;code&gt;UsersController&lt;/code&gt;, &lt;code&gt;QuestionsController&lt;/code&gt; and &lt;code&gt;CategoriesController&lt;/code&gt;. These &lt;em&gt;namespaced&lt;/em&gt; routes and their respective controllers nomenclature help tremendously in setting up filenames hierarchy. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note — make sure the PostgreSQL 🐘  is running while configuring routes and controllers.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Api::UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
        &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt; 
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="no"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt; 
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="no"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;status: :accepted&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;full_messages&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt; 
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; 
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; 
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="s1"&gt;'User not found.'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt; 
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; 
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="s1"&gt;'User not saved.'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="kp"&gt;private&lt;/span&gt; 

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_params&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:animals_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:celebrities_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:computer_science_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:geography_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:history_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:mathematics_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:music_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sports_score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I will only have the &lt;code&gt;UsersController&lt;/code&gt; displayed here, and briefly convey the &lt;code&gt;render json&lt;/code&gt;. My rails routes only strictly render JSON strings. This is useful when building JavaScript front-end on DOM manipulation and performing asynchronous requests. The &lt;code&gt;user_params&lt;/code&gt; on &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;avatar&lt;/code&gt; and all category &lt;code&gt;scores&lt;/code&gt; will be included in the body of &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;PATCH&lt;/code&gt; requests when executing &lt;code&gt;fetch&lt;/code&gt;. &lt;code&gt;status: :accepted&lt;/code&gt; helps to inform the user of the &lt;a href="https://httpstatuses.com/202" rel="noopener noreferrer"&gt;success 202 HTML status&lt;/a&gt; when submitting user input forms on the front-end application. If it fails to save, &lt;code&gt;status: :unprocessable_entity&lt;/code&gt; notifies the &lt;a href="https://httpstatuses.com/422" rel="noopener noreferrer"&gt;client error 422 HTML status&lt;/a&gt;.&lt;/p&gt;
&lt;h5&gt;
  
  
  Serializers
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;gem 'fast_jsonapi'&lt;/code&gt; is a &lt;a href="https://github.com/Netflix/fast_jsonapi#table-of-contents" rel="noopener noreferrer"&gt;JSON serializer&lt;/a&gt; for Rails APIs. It allows us to generate &lt;em&gt;serializer&lt;/em&gt; classes. The goal of a serializer class is to keep controllers clear of excess logic, including  arranging my JSON data to display certain object attributes. It does not hurt to practice serializer early on, even though the current state of my &lt;strong&gt;Minimum Viable Product (MVP)&lt;/strong&gt; does not necessarily require one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1292fv1uicgs1mbk6ubl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1292fv1uicgs1mbk6ubl.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  5. Communicating with the Server &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;In order to make sure the Rails server back-end API worked, I tested a few &lt;strong&gt;Asynchronous JavaScript and XML (AJAX)&lt;/strong&gt; calls on my browser console. While I have been using a lot of &lt;code&gt;fetch()&lt;/code&gt; for this project, I have yet to challenge myself with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" rel="noopener noreferrer"&gt;&lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt; function&lt;/a&gt;. I am glad my initial attempt of &lt;code&gt;fetch()&lt;/code&gt; in browser console made successful requests. Moving on to front-end!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit" rel="noopener noreferrer"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/KnowItAll_backend" rel="noopener noreferrer"&gt;
        KnowItAll_backend
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The MVP of Know It All app is to create a basic Trivia game on Single-Page Application (SPA). This project is built with Ruby on Rails back-end and JavaScript front-end.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Know It All :: Back-End&lt;/h1&gt;
&lt;/div&gt;

&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/KnowItAll_backendserializer.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FKnowItAll_backendserializer.gif"&gt;&lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Domain Modeling :: Trivia Games&lt;/strong&gt;&lt;br&gt;
Welcome to my simplistic version of Online Trivia Games.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/fentybit/KnowItAll_frontend" rel="noopener noreferrer"&gt;Front-End GitHub Repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/kU_Ay68TWcM" rel="nofollow noopener noreferrer"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/know-it-all-2kpp" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The Minimum Viable Product (MVP) of &lt;strong&gt;Know It All&lt;/strong&gt; is to provide the User with few trivia Categories to select from.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/KnowItAll_backenderd.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FKnowItAll_backenderd.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Models&lt;/strong&gt; &lt;br&gt;
User, Category&lt;br&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;user &lt;code&gt;has_many&lt;/code&gt; :categories&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;category &lt;code&gt;belongs_to&lt;/code&gt; :user&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; &lt;br&gt;
ApplicationController&lt;br&gt;
UsersController&lt;br&gt;
CategoriesController&lt;br&gt;
QuestionsController&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Database&lt;/h2&gt;

&lt;/div&gt;
&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 &lt;a href="https://opentdb.com/" rel="nofollow noopener noreferrer"&gt;Open Trivia Database&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Free to use, user-contributed trivia question database.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Back-End&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-ruby notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;$ &lt;span class="pl-en"&gt;git&lt;/span&gt; &lt;span class="pl-en"&gt;clone&lt;/span&gt; &lt;span class="pl-en"&gt;👾&lt;/span&gt;
$ &lt;span class="pl-en"&gt;bundle&lt;/span&gt; &lt;span class="pl-en"&gt;install&lt;/span&gt;
$ &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-pds"&gt;db&lt;/span&gt;:&lt;span class="pl-en"&gt;create&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-en"&gt;db&lt;/span&gt;&lt;span class="pl-pds"&gt;:migrate&lt;/span&gt;
$ &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-pds"&gt;db&lt;/span&gt;:&lt;span class="pl-en"&gt;seed&lt;/span&gt;
$ &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-en"&gt;s&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open Chrome browser, and redirect to '&lt;a href="http://localhost:3000" rel="nofollow noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;' to start the Rails API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Front-End&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Open Chrome browser, and redirect to '&lt;a href="http://127.0.0.1:5500/index.html" rel="nofollow noopener noreferrer"&gt;http://127.0.0.1:5500/index.html&lt;/a&gt;' to start the app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alternatively, it is fully deployed on Netlify!&lt;/strong&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lets-know-it-all.netlify.app/" rel="nofollow noopener noreferrer"&gt;Know It All&lt;/a&gt;&lt;/p&gt;
Feel free to use &lt;strong&gt;David Strong&lt;/strong&gt; to sign in!
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Build Status&lt;/h2&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/KnowItAll_backend" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h3&gt;
  
  
  Front-End Web Programming
&lt;/h3&gt;

&lt;p&gt;I have to say this part is my most challenging part! I was struggling to gather all of my new knowledge of &lt;strong&gt;The Three Pillars of Web Programming&lt;/strong&gt;: &lt;em&gt;recognizing JavaScript events, Document Object Model (DOM) manipulation, and communicating with the server on a Single-Page Application (SPA)&lt;/em&gt;. Separation of concerns, as a fundamental programming concept, is still applicable. &lt;strong&gt;HTML&lt;/strong&gt; defines the &lt;em&gt;structure of the website&lt;/em&gt;, &lt;strong&gt;JavaScript&lt;/strong&gt; provides &lt;em&gt;functionality&lt;/em&gt; and &lt;strong&gt;CSS&lt;/strong&gt; defines the &lt;em&gt;visual presentation&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. DOM Manipulation with JavaScript Event Listeners &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;It took me a few days practicing on a set of hard-coded trivia questions and having my trivia cards update as the user progresses to the next question. Know It All includes a score tracker, questions quantity, progress bar, along with passing and/or failing User Interface (UI) alerts. Having Single-Page Application (SPA) required me to create an element with &lt;code&gt;document.createElement('...')&lt;/code&gt; multiple times, and using either &lt;code&gt;.append()&lt;/code&gt; or &lt;code&gt;.appendChild()&lt;/code&gt; often. Also, trying to incorporate Bootstrap CSS early resulted in a slow and unproductive debugging process. A part of me loves spending gazillion hours on CSS elements. &lt;em&gt;Note to self — do not waste your time on CSS!&lt;/em&gt; 😅&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuhtkechgocews1de7pf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuhtkechgocews1de7pf.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One particular challenge I found was to gather user input fields and update their back-end values with asynchronous JavaScript &lt;code&gt;PATCH&lt;/code&gt;. Later I found that I got stuck on an erroneous &lt;code&gt;fetch&lt;/code&gt; url, and corrected my string template literals to &lt;code&gt;${this.url}/${currentUser.id}&lt;/code&gt;. While I used a lot of &lt;code&gt;standard&lt;/code&gt; and &lt;code&gt;static&lt;/code&gt; methods in my OO JavaScript, I plan to explore both &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; methods.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Re-factoring Early &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;After spending sometime working on basic event handlings, my &lt;code&gt;index.js&lt;/code&gt; file piled up easily with 200+ lines of code. While I have spent the past month on &lt;a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0" rel="noopener noreferrer"&gt;JavaScript Functional Programming&lt;/a&gt;, &lt;strong&gt;Object-Oriented (OO) JavaScript&lt;/strong&gt; offers better data control, easy to replicate (with &lt;code&gt;constructor&lt;/code&gt; method and &lt;code&gt;new&lt;/code&gt; syntax), and grants us the ability to write code that convey these relationships. I decided to build &lt;code&gt;class&lt;/code&gt;es and their &lt;em&gt;execution contexts&lt;/em&gt; in separate files, &lt;code&gt;api.js&lt;/code&gt;, &lt;code&gt;category.js&lt;/code&gt;, &lt;code&gt;user.js&lt;/code&gt; and &lt;code&gt;question.js&lt;/code&gt;. Each &lt;code&gt;class&lt;/code&gt; has its own &lt;em&gt;lexical scope&lt;/em&gt; of variables and functions, leaving &lt;code&gt;index.js&lt;/code&gt; with global variables and callback functions necessary to support &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fki08wso6ptq3wlca53ga.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fki08wso6ptq3wlca53ga.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During this re-factoring exercise, I also removed all of my &lt;code&gt;var&lt;/code&gt;s, and replaced them with either &lt;code&gt;const&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt;. Variables declared with &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; are &lt;em&gt;block-scoped&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. End Page Sequence &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Drum roll... 🥁  We are now coming close to an end. After each set of trivia questions, users should be able to see their final score, and whether or not they beat their previous score. If they do, the new (or higher) score will be saved in the Rails API user database. There will be two options for the user to either &lt;code&gt;Play Again&lt;/code&gt; or return back to &lt;code&gt;Home&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72vg4ykqygga7asrfuuw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72vg4ykqygga7asrfuuw.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Lessons Learned &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;After months of &lt;code&gt;GitHub&lt;/code&gt;ing, I am getting really comfortable with working on a separate branch, and merge to master. The git command &lt;code&gt;git co -b &amp;lt;branch_name&amp;gt;&lt;/code&gt; becomes my go-to &lt;code&gt;git&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;Understanding JavaScript's syntax and semantics after months dwelling on Ruby has been fun. For example, in JavaScript, functions are treated as &lt;em&gt;first-class&lt;/em&gt; data, and understanding some of the concepts of &lt;em&gt;hoisting&lt;/em&gt; and &lt;a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down" rel="noopener noreferrer"&gt;scope chain&lt;/a&gt;. JavaScript engine works in &lt;em&gt;compilation&lt;/em&gt; phase and &lt;em&gt;execution&lt;/em&gt; phase. Since I used a lot of JavaScript event &lt;code&gt;click&lt;/code&gt; and &lt;code&gt;submit&lt;/code&gt; for this project build, I would love to explore &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Events" rel="noopener noreferrer"&gt;other browser events&lt;/a&gt;. This &lt;a href="https://youtu.be/Bv_5Zv5c-Ts" rel="noopener noreferrer"&gt;YouTube tutorial&lt;/a&gt; helped me tremendously to better understand the weird parts of JavaScript.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit" rel="noopener noreferrer"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/KnowItAll_frontend" rel="noopener noreferrer"&gt;
        KnowItAll_frontend
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The MVP of Know It All app is to create a basic Trivia game on Single-Page Application (SPA). This project is built with Ruby on Rails back-end and JavaScript front-end.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Know It All :: Front-End&lt;/h1&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/KnowItAll_frontendimages/main.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FKnowItAll_frontendimages%2Fmain.gif"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Domain Modeling :: Trivia Games&lt;/strong&gt;&lt;br&gt;
Welcome to my simplistic version of Online Trivia Games.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/fentybit/KnowItAll_backend" rel="noopener noreferrer"&gt;Back-End GitHub Repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/kU_Ay68TWcM" rel="nofollow noopener noreferrer"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/know-it-all-2kpp" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The Minimum Viable Product (MVP) of &lt;strong&gt;Know It All&lt;/strong&gt; is to provide the User with few trivia Categories to select from.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/KnowItAll_frontendimages/erd.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Ffentybit%2FKnowItAll_frontendimages%2Ferd.png"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Models&lt;/strong&gt; &lt;br&gt;
User, Category&lt;br&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;user &lt;code&gt;has_many&lt;/code&gt; :categories&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;category &lt;code&gt;belongs_to&lt;/code&gt; :user&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; &lt;br&gt;
ApplicationController&lt;br&gt;
UsersController&lt;br&gt;
CategoriesController&lt;br&gt;
QuestionsController&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Database&lt;/h2&gt;

&lt;/div&gt;
&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 &lt;a href="https://opentdb.com/" rel="nofollow noopener noreferrer"&gt;Open Trivia Database&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Free to use, user-contributed trivia question database.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Back-End&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-ruby notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;$ &lt;span class="pl-en"&gt;git&lt;/span&gt; &lt;span class="pl-en"&gt;clone&lt;/span&gt; &lt;span class="pl-en"&gt;👾&lt;/span&gt;
$ &lt;span class="pl-en"&gt;bundle&lt;/span&gt; &lt;span class="pl-en"&gt;install&lt;/span&gt;
$ &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-pds"&gt;db&lt;/span&gt;:&lt;span class="pl-en"&gt;create&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-en"&gt;db&lt;/span&gt;&lt;span class="pl-pds"&gt;:migrate&lt;/span&gt;
$ &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-pds"&gt;db&lt;/span&gt;:&lt;span class="pl-en"&gt;seed&lt;/span&gt;
$ &lt;span class="pl-en"&gt;rails&lt;/span&gt; &lt;span class="pl-en"&gt;s&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open Chrome browser, and redirect to '&lt;a href="http://localhost:3000" rel="nofollow noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;' to start the Rails API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Front-End&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Open Chrome browser, and redirect to '&lt;a href="http://127.0.0.1:5500/index.html" rel="nofollow noopener noreferrer"&gt;http://127.0.0.1:5500/index.html&lt;/a&gt;' to start the app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alternatively, it is fully deployed on Netlify!&lt;/strong&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lets-know-it-all.netlify.app/" rel="nofollow noopener noreferrer"&gt;Know It All&lt;/a&gt;&lt;/p&gt;
Feel free to use &lt;strong&gt;David Strong&lt;/strong&gt; to sign in!
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Build Status&lt;/h2&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/KnowItAll_frontend" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h3&gt;
  
  
  Build Status and Future Improvement
&lt;/h3&gt;

&lt;p&gt;Know It All was completed in a 2-week timeframe from API data search, Ruby on Rails back-end, and JavaScript front-end User Interface. Future cycle of product development as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Add &lt;code&gt;Sub Category&lt;/code&gt; to model associations. User should be able to select &lt;code&gt;Category&lt;/code&gt; and its &lt;code&gt;Sub Category&lt;/code&gt;. For example, science category has many sub categories including physics, mathematics, biology and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5dxmoafn6rlb1tb1dvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5dxmoafn6rlb1tb1dvq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Outsource APIs for the aforementioned &lt;code&gt;Sub Category&lt;/code&gt; trivia questions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gather user inputs on their favorite &lt;code&gt;Category&lt;/code&gt; on future app improvement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Utilize &lt;code&gt;setInterval&lt;/code&gt; and/or time limit of 15-20 seconds on each Trivia question.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User authentication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a toggle track for dark mode 😎&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Post Scriptum:&lt;br&gt;
This is my Module 3 capstone project with Flatiron School. I believe one of the catalyst to becoming a good programmer is to welcome constructive criticism. Feel free to drop a message. 🙂&lt;/p&gt;

&lt;p&gt;Keep Calm, and Code On.&lt;/p&gt;

&lt;p&gt;External Sources:&lt;br&gt;
&lt;a href="https://opentdb.com/" rel="noopener noreferrer"&gt;Open Trivia Database&lt;/a&gt;&lt;br&gt;
&lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;CSS Bootstrap&lt;/a&gt;&lt;br&gt;
&lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;center&gt;[**fentybit**](https://fentybit.me/) | [GitHub](https://github.com/fentybit) | [Twitter](https://twitter.com/fentybit) | [LinkedIn](https://www.linkedin.com/in/fentybit/)&lt;/center&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>Plan My MD Visit Part 2</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Fri, 19 Feb 2021 18:19:14 +0000</pubDate>
      <link>https://forem.com/fentybit/plan-my-md-visit-part-2-1dkk</link>
      <guid>https://forem.com/fentybit/plan-my-md-visit-part-2-1dkk</guid>
      <description>&lt;p&gt;I have decided to fine-tune &lt;strong&gt;&lt;a href="https://plan-my-md-visit.herokuapp.com/"&gt;Plan My MD Visit&lt;/a&gt;&lt;/strong&gt; after receiving feedback from fellow developers on responsive web design and future build status.&lt;/p&gt;

&lt;h3&gt;
  
  
  Responsive Web Design
&lt;/h3&gt;

&lt;p&gt;Previous front-end built was centered around the users navigating through web browser. I went back, adjusted CSS/style classes, and added the &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag for mobile phone users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;PlanMyMdVisit&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;csrf_meta_tags&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;csp_meta_tag&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=0.9"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    ...

  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://plan-my-md-visit.herokuapp.com/"&gt;Plan My MD Visit&lt;/a&gt;&lt;/strong&gt; is now responsive on mobile, tablet and desktop browser! 🌟&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z8WHrUxW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7pxygvhz57r7zffk0dx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z8WHrUxW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7pxygvhz57r7zffk0dx.gif" alt="Alt Text" width="600" height="1297"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Build Status and Future Improvement
&lt;/h3&gt;

&lt;p&gt;Current project-built was completed in a 2-week timeframe from API data search, model association development, and MVP for both patient and admin user interface. &lt;br&gt;
Future cycle of product development as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;Healthcare Provider&lt;/code&gt; to model associations. Patients can find their healthcare providers, and sort through in-network doctors by their specialties.&lt;/li&gt;
&lt;li&gt;Outsource from different APIs for doctors, currently restricted to Medicare Care Compare eligible professionals.&lt;/li&gt;
&lt;li&gt;Develop user interface for users as doctors.&lt;/li&gt;
&lt;li&gt;Set up customized validations for scheduling appointments where each individual doctor can personalize their preferred schedule.&lt;/li&gt;
&lt;li&gt;Communication features (i.e., private messaging) in between doctors and patients.&lt;/li&gt;
&lt;li&gt;Design separate CSS layouts for different user groups: patients, admins and doctors.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/PlanMyMDVisit"&gt;
        PlanMyMDVisit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The MVP of Plan My MD Visit app is to create a virtual patient system where the automation benefits patient 24/7 seeking virtual medical assistance, improving overall patient well-being. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Plan My MD Visit&lt;/h1&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/PlanMyMDVisitapp/assets/images/readme_main.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YPYjDxsf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/fentybit/PlanMyMDVisitapp/assets/images/readme_main.gif"&gt;&lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Domain Modeling :: Virtual Healthcare&lt;/strong&gt;&lt;br&gt;
Welcome to my simplistic version of Virtual Healthcare system.&lt;br&gt;
The automation benefits patients 24/7 seeking medical assistance, improving overall patient well-being!&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/0cRPsyLgx88" rel="nofollow"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/plan-my-md-visit-c0l" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
About&lt;/h2&gt;
&lt;p&gt;The pandemic that has been lingering all around us since early 2020 has caused an apparent challenge to the current healthcare system. It is a testament to the new modern demand of digital healthcare. The conventional healthcare system is currently overflown with predominantly Covid-19 patients, exceeding their abilities to facilitate care of other medical patient needs.&lt;/p&gt;
&lt;p&gt;The Minimum Viable Product (MVP) of Plan My MD Visit app is to create a virtual patient system where the automation benefits patient 24/7 seeking virtual medical assistance, improving overall patient well-being. My application carries essential features and minimal attributes of tele-health platforms. Patients make their visits to the clinic, laboratory or hospital only when necessary and/or advised by…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/PlanMyMDVisit"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;Post Scriptum:&lt;br&gt;
This is my Module 3 capstone project with Flatiron School. I believe one of the catalyst to becoming a good programmer is to welcome constructive criticism. Feel free to drop a message. 🙂&lt;/p&gt;

&lt;p&gt;Keep Calm, and Code On.&lt;/p&gt;






&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Deploy Ruby on Rails on Heroku</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sun, 31 Jan 2021 20:55:02 +0000</pubDate>
      <link>https://forem.com/fentybit/deploy-ruby-on-rails-on-heroku-5dn7</link>
      <guid>https://forem.com/fentybit/deploy-ruby-on-rails-on-heroku-5dn7</guid>
      <description>&lt;p&gt;My first deployment with Heroku did not go as smoothly as I anticipated. I decided to document and share my Heroku journey. I can only share some of the hurdles from my &lt;a href="https://dev.to/codinghall/plan-my-md-visit-c0l"&gt;Plan My MD Visit&lt;/a&gt; app. Previously, the project was built and completed by running '&lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;'. My recommendation to fellow developers would be to deploy early and debug as you progress through the project. It is more time efficient than discovering a large number of glitches near the end of the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;First things first&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqryg5a4i471z361fyw4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqryg5a4i471z361fyw4t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sign Up with &lt;a href="https://signup.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It provides free cloud services for developers to run their applications. Make sure you read their &lt;a href="https://www.heroku.com/free" rel="noopener noreferrer"&gt;provisions&lt;/a&gt; for their free platform services.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;SQLite &amp;gt; PostgreSQL&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If your application is currently running on SQLite database, there are two action items:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Gemfile&lt;/code&gt; and &lt;em&gt;SQL query in PostgreSQL&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Gem &lt;code&gt;sqlite3&lt;/code&gt; will be decommissioned, and replaced by gem &lt;code&gt;pg&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# gem 'sqlite3', '~&amp;gt; 1.4'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'pg'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;bundle install&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We will circle back to &lt;em&gt;SQL query in PostgreSQL&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Update &lt;code&gt;config/database.yml&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This file was created by default when we initiated the Rails app with &lt;code&gt;$ rails new app-name&lt;/code&gt;. Rails provides a database with &lt;code&gt;sqlite3&lt;/code&gt; adapter, and its pre-built code as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# SQLite. Versions 3.8.0 and up are supported.&lt;/span&gt;
&lt;span class="c1"&gt;#   gem install sqlite3&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   Ensure the SQLite 3 gem is defined in your Gemfile&lt;/span&gt;
&lt;span class="c1"&gt;#   gem 'sqlite3'&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;
  &lt;span class="ss"&gt;adapter: &lt;/span&gt;&lt;span class="n"&gt;sqlite3&lt;/span&gt;
  &lt;span class="ss"&gt;pool: &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %&amp;gt;
  timeout: 5000

development:
  &amp;lt;&amp;lt;: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  &amp;lt;&amp;lt;: *default
  database: db/test.sqlite3

production:
  &amp;lt;&amp;lt;: *default
  database: db/production.sqlite3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to adjust it for &lt;code&gt;postgresql&lt;/code&gt;. While perusing &lt;a href="https://devcenter.heroku.com/articles/rails-database-connection-behavior" rel="noopener noreferrer"&gt;Heroku documentation&lt;/a&gt; and &lt;a href="https://gist.github.com/jwo/4512764" rel="noopener noreferrer"&gt;GitHub gist&lt;/a&gt;, I was able to revise my code in &lt;code&gt;config/database.yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# PostgreSQL. Versions 8.2 and up are supported.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Install the pg driver:&lt;/span&gt;
&lt;span class="c1"&gt;#   gem install pg&lt;/span&gt;
&lt;span class="c1"&gt;# On Mac OS X with macports:&lt;/span&gt;
&lt;span class="c1"&gt;#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config&lt;/span&gt;
&lt;span class="c1"&gt;# On Windows:&lt;/span&gt;
&lt;span class="c1"&gt;#   gem install pg&lt;/span&gt;
&lt;span class="c1"&gt;#       Choose the win32 build.&lt;/span&gt;
&lt;span class="c1"&gt;#       Install PostgreSQL and put its /bin directory on your path.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Configure Using Gemfile&lt;/span&gt;
&lt;span class="c1"&gt;# gem 'pg'&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="ss"&gt;development:
  adapter: &lt;/span&gt;&lt;span class="n"&gt;postgresql&lt;/span&gt;
  &lt;span class="ss"&gt;encoding: &lt;/span&gt;&lt;span class="n"&gt;unicode&lt;/span&gt;
  &lt;span class="ss"&gt;database: &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name_development&lt;/span&gt;
  &lt;span class="ss"&gt;pool: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
  &lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="n"&gt;your_username&lt;/span&gt;
  &lt;span class="ss"&gt;password:

  &lt;/span&gt;&lt;span class="c1"&gt;# Connect on a TCP socket. Omitted by default since the client uses a&lt;/span&gt;
  &lt;span class="c1"&gt;# domain socket that doesn't need configuration. Windows does not have&lt;/span&gt;
  &lt;span class="c1"&gt;# domain sockets, so uncomment these lines.&lt;/span&gt;
  &lt;span class="c1"&gt;#host: localhost&lt;/span&gt;
  &lt;span class="c1"&gt;#port: 5432&lt;/span&gt;

  &lt;span class="c1"&gt;# Schema search path. The server defaults to $user,public&lt;/span&gt;
  &lt;span class="c1"&gt;#schema_search_path: myapp,sharedapp,public&lt;/span&gt;

  &lt;span class="c1"&gt;# Minimum log levels, in increasing order:&lt;/span&gt;
  &lt;span class="c1"&gt;#   debug5, debug4, debug3, debug2, debug1,&lt;/span&gt;
  &lt;span class="c1"&gt;#   log, notice, warning, error, fatal, and panic&lt;/span&gt;
  &lt;span class="c1"&gt;# The server defaults to notice.&lt;/span&gt;
  &lt;span class="c1"&gt;#min_messages: warning&lt;/span&gt;

&lt;span class="c1"&gt;# Warning: The database defined as "test" will be erased and&lt;/span&gt;
&lt;span class="c1"&gt;# re-generated from your development database when you run "rake".&lt;/span&gt;
&lt;span class="c1"&gt;# Do not set this db to the same as development or production.&lt;/span&gt;
&lt;span class="ss"&gt;test:
  adapter: &lt;/span&gt;&lt;span class="n"&gt;postgresql&lt;/span&gt;
  &lt;span class="ss"&gt;encoding: &lt;/span&gt;&lt;span class="n"&gt;unicode&lt;/span&gt;
  &lt;span class="ss"&gt;database: &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name_test&lt;/span&gt;
  &lt;span class="ss"&gt;pool: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
  &lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="n"&gt;your_username&lt;/span&gt;
  &lt;span class="ss"&gt;password:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is important.&lt;/strong&gt; &lt;code&gt;git push&lt;/code&gt;, and always try to maintain latest repo files in your GitHub account.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Heroku CLI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Follow the initial &lt;a href="https://devcenter.heroku.com/articles/heroku-cli#download-and-install" rel="noopener noreferrer"&gt;Heroku CLI setup&lt;/a&gt;. Once installed, you can type &lt;code&gt;$ heroku login&lt;/code&gt; on the terminal. You will receive a return feedback as displayed below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="ss"&gt;heroku: &lt;/span&gt;&lt;span class="no"&gt;Press&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="ss"&gt;exit:
&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="no"&gt;Opening&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="ss"&gt;:/&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;heroku&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;/...&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="n"&gt;requestor&lt;/span&gt;&lt;span class="o"&gt;=...&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="no"&gt;Logging&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="no"&gt;Logged&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;your_email&lt;/span&gt;&lt;span class="vi"&gt;@email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;com&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F72do04f2n7z1or27a1pn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F72do04f2n7z1or27a1pn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will then navigate you to Heroku web browser to log in. You may close the web page after you successfully log in, and return to VSCode terminal. With &lt;code&gt;heroku&lt;/code&gt; command prompt, you will see Heroku Command Line Interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; 
    &lt;span class="no"&gt;CLI&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;interact&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;

    &lt;span class="no"&gt;VERSION&lt;/span&gt;
      &lt;span class="n"&gt;heroku&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;7.47&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="n"&gt;darwin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x64&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v12&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;16.2&lt;/span&gt;

    &lt;span class="no"&gt;USAGE&lt;/span&gt;
      &lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;COMMAND&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="no"&gt;COMMANDS&lt;/span&gt;
      &lt;span class="n"&gt;access&lt;/span&gt;          &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;
      &lt;span class="n"&gt;addons&lt;/span&gt;          &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;developing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;operating&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
      &lt;span class="n"&gt;apps&lt;/span&gt;            &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;
      &lt;span class="n"&gt;auth&lt;/span&gt;            &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;fa&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
      &lt;span class="n"&gt;authorizations&lt;/span&gt;  &lt;span class="no"&gt;OAuth&lt;/span&gt; &lt;span class="n"&gt;authorizations&lt;/span&gt;
      &lt;span class="n"&gt;autocomplete&lt;/span&gt;    &lt;span class="nb"&gt;display&lt;/span&gt; &lt;span class="n"&gt;autocomplete&lt;/span&gt; &lt;span class="n"&gt;installation&lt;/span&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;
      &lt;span class="n"&gt;buildpacks&lt;/span&gt;      &lt;span class="n"&gt;scripts&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;compile&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;
      &lt;span class="n"&gt;certs&lt;/span&gt;           &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ssl&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;
      &lt;span class="n"&gt;ci&lt;/span&gt;              &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;
      &lt;span class="n"&gt;clients&lt;/span&gt;         &lt;span class="no"&gt;OAuth&lt;/span&gt; &lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;
      &lt;span class="n"&gt;config&lt;/span&gt;          &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="n"&gt;variables&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;
      &lt;span class="n"&gt;container&lt;/span&gt;       &lt;span class="no"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;containers&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;
      &lt;span class="n"&gt;domains&lt;/span&gt;         &lt;span class="n"&gt;custom&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;
      &lt;span class="n"&gt;drains&lt;/span&gt;          &lt;span class="n"&gt;forward&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;syslog&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="no"&gt;HTTPS&lt;/span&gt;
      &lt;span class="n"&gt;features&lt;/span&gt;        &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;
      &lt;span class="n"&gt;git&lt;/span&gt;             &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
      &lt;span class="n"&gt;help&lt;/span&gt;            &lt;span class="nb"&gt;display&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt;
      &lt;span class="n"&gt;keys&lt;/span&gt;            &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="n"&gt;ssh&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;
      &lt;span class="n"&gt;labs&lt;/span&gt;            &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;experimental&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;
      &lt;span class="n"&gt;local&lt;/span&gt;           &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="n"&gt;locally&lt;/span&gt;
      &lt;span class="n"&gt;logs&lt;/span&gt;            &lt;span class="nb"&gt;display&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
      &lt;span class="n"&gt;maintenance&lt;/span&gt;     &lt;span class="n"&gt;enable&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;disable&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
      &lt;span class="n"&gt;members&lt;/span&gt;         &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;organization&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt;
      &lt;span class="n"&gt;notifications&lt;/span&gt;   &lt;span class="nb"&gt;display&lt;/span&gt; &lt;span class="n"&gt;notifications&lt;/span&gt;
      &lt;span class="n"&gt;orgs&lt;/span&gt;            &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;organizations&lt;/span&gt;
      &lt;span class="n"&gt;pg&lt;/span&gt;              &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;postgresql&lt;/span&gt; &lt;span class="n"&gt;databases&lt;/span&gt;
      &lt;span class="n"&gt;pipelines&lt;/span&gt;       &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;pipelines&lt;/span&gt;
      &lt;span class="n"&gt;plugins&lt;/span&gt;         &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;installed&lt;/span&gt; &lt;span class="n"&gt;plugins&lt;/span&gt;
      &lt;span class="n"&gt;ps&lt;/span&gt;              &lt;span class="no"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt; &lt;span class="no"&gt;Exec&lt;/span&gt;
      &lt;span class="n"&gt;psql&lt;/span&gt;            &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;psql&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;
      &lt;span class="n"&gt;redis&lt;/span&gt;           &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;
      &lt;span class="n"&gt;regions&lt;/span&gt;         &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt; &lt;span class="n"&gt;regions&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;deployment&lt;/span&gt;
      &lt;span class="n"&gt;releases&lt;/span&gt;        &lt;span class="nb"&gt;display&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;releases&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
      &lt;span class="n"&gt;reviewapps&lt;/span&gt;      &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;reviewapps&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pipelines&lt;/span&gt;
      &lt;span class="n"&gt;run&lt;/span&gt;             &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;off&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="n"&gt;inside&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt; &lt;span class="n"&gt;dyno&lt;/span&gt;
      &lt;span class="n"&gt;sessions&lt;/span&gt;        &lt;span class="no"&gt;OAuth&lt;/span&gt; &lt;span class="n"&gt;sessions&lt;/span&gt;
      &lt;span class="n"&gt;spaces&lt;/span&gt;          &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="kp"&gt;private&lt;/span&gt; &lt;span class="n"&gt;spaces&lt;/span&gt;
      &lt;span class="n"&gt;status&lt;/span&gt;          &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;
      &lt;span class="n"&gt;teams&lt;/span&gt;           &lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;teams&lt;/span&gt;
      &lt;span class="n"&gt;update&lt;/span&gt;          &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt; &lt;span class="no"&gt;CLI&lt;/span&gt;
      &lt;span class="n"&gt;webhooks&lt;/span&gt;        &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;webhooks&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few ways to create a Heroku app, either from Heroku CLI or web browser. With the CLI, you can create a new Heroku app with &lt;code&gt;$ heroku create&lt;/code&gt;. This prompt gives you the default &lt;a href="https://devcenter.heroku.com/articles/heroku-20-stack" rel="noopener noreferrer"&gt;Heroku-20 stack&lt;/a&gt;. It depends on your Ruby buildpack, and Heroku-20 did not align with my project build. I reviewed &lt;a href="https://devcenter.heroku.com/categories/stacks" rel="noopener noreferrer"&gt;Heroku stacks documentation&lt;/a&gt;, and found &lt;a href="https://devcenter.heroku.com/articles/heroku-18-stack" rel="noopener noreferrer"&gt;Heroku-18&lt;/a&gt; stack worked with my Ruby version 2.6.1.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Heroku Database&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once Heroku app is successfully created, we can push the code to the Heroku server with command line &lt;code&gt;$ git push heroku master&lt;/code&gt;. At this point, if you still hit a snag, I highly recommend Google search — lots of Stack Overflow and tutorials from other devs. For my project, it successfully deployed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="ss"&gt;:migrate&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="ss"&gt;:seed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we are migrating our database to Heroku's PostgreSQL, we need to initiate the command lines above. &lt;code&gt;heroku run rails db:seed&lt;/code&gt; is necessary when you have seeding data, either fetching API data or manual &lt;code&gt;seeds.rb&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;PostgreSQL - JOIN clause&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Circling back to &lt;em&gt;SQL query in PostgreSQL&lt;/em&gt;, this part frustrates me the most. At one point, I hit an impasse, and thought my deployment process was fully corrupted. My application was up and running. However, as I was navigating all links and forms, I was not able to proceed with a few form selections. Heroku's error notification did not provide with enough detailed information to understand what was wrong.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We're sorry, but something went wrong.&lt;br&gt;
If you are the application owner check the logs for more information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I gave up that night, slept and continued debugging the next day. 😥&lt;/p&gt;

&lt;p&gt;After spending a few hours on Stack Overflow, I learned that my SQL query on helper methods needed refactoring following PostgreSQL. I suggest reviewing all query statements to &lt;a href="https://www.postgresql.org/docs/8.3/tutorial-join.html" rel="noopener noreferrer"&gt;PostgreSQL query documentation&lt;/a&gt;. One debugging example for the &lt;code&gt;JOIN&lt;/code&gt; query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# SQLite query on JOIN&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doctors&lt;/span&gt; 
  &lt;span class="n"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:doctor&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# PostgreSQL query on JOIN&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doctors&lt;/span&gt; 
  &lt;span class="n"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:doctor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Authentication&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Last hurdle was on migrating &lt;code&gt;PROVIDER_CLIENT_ID&lt;/code&gt; and &lt;code&gt;PROVIDER_SECRET&lt;/code&gt; from &lt;code&gt;.env&lt;/code&gt; to Heroku. In Heroku browser, you can navigate to your &lt;em&gt;app &amp;gt; Settings &amp;gt; Config Vars &amp;gt; Reveal Config Vars&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fknr6pqkabcisfxxh21u8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fknr6pqkabcisfxxh21u8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This concludes the journey of my first RoR deployment with Heroku.&lt;/p&gt;

&lt;p&gt;I intend to exploring future project builds with Heroku, and share my experience with other devs. Thank you, Heroku. 👾&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Drum roll.... 🥁&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Below is my first Ruby on Rails deployment on Heroku!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj5szx8gapeu9l7f5tc7c.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj5szx8gapeu9l7f5tc7c.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;center&gt;[**fentybit**](https://fentybit.me/) | [GitHub](https://github.com/fentybit) | [Twitter](https://twitter.com/fentybit) | [LinkedIn](https://www.linkedin.com/in/fentybit/)&lt;/center&gt;

</description>
      <category>heroku</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Plan My MD Visit Part 1</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Tue, 19 Jan 2021 04:24:21 +0000</pubDate>
      <link>https://forem.com/fentybit/plan-my-md-visit-c0l</link>
      <guid>https://forem.com/fentybit/plan-my-md-visit-c0l</guid>
      <description>&lt;p&gt;Happy New Year 2021, fellow devs!&lt;/p&gt;

&lt;p&gt;Moving along from my previous Intro to Rails study, &lt;a href="https://dev.to/codinghall/rails-intro-mandalorian-1ppp"&gt;Rails Intro::Mandalorian&lt;/a&gt;, my cohort is approaching the Ruby on Rails deadline week. Since Rails provides more powerful web application frameworks compared to my previous &lt;a href="https://dev.to/codinghall/sinatra-x-street-fighter-1hgl"&gt;Sinatra Project Build&lt;/a&gt;, it allows swift implementation of a more complex model associations and corresponding attributes.&lt;br&gt;
The pandemic that has been lingering all around us since early 2020 has caused an apparent challenge to the current healthcare system. It is a testament to the new modern demand of digital healthcare. The conventional healthcare system is currently overflown with predominantly Covid-19 patients, exceeding their abilities to facilitate care of other medical patient needs. The Minimum Viable Product (MVP) of &lt;strong&gt;Plan My MD Visit&lt;/strong&gt; app is to create a virtual patient system where the automation benefits patient 24/7 seeking virtual medical assistance, improving overall patient well-being. My application carries essential features and minimal attributes of tele-health platforms. Patients make their visits to the clinic, laboratory or hospital only when necessary and/or advised by medical professionals. &lt;/p&gt;
&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;p&gt;1. User Story&lt;br&gt;
2. API Searching Saga&lt;br&gt;
3. Creating Active Record Model&lt;br&gt;
4. Action Controllers&lt;br&gt;
5. Authentication and Authorization Terms&lt;br&gt;
6. Action Views&lt;br&gt;
7. Lastly, as always - Lessons Learned&lt;/p&gt;
&lt;h3&gt;
  
  
  1. User Story &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I spent most of my time at the inception of this project, thinking who the users are and what their experiences would be. At first, I came up with 5 different models that encapsulate the majority party in the healthcare platform; users as either patients, doctors, nurses, administrators, healthcare teams and healthcare providers. The brainstorming exercise goes hand in hand with my attempt in data searching — which presents its own sets of challenges. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I-YInX0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a6s406uulnu3cm529yqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I-YInX0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a6s406uulnu3cm529yqw.png" alt="Alt Text" width="880" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I focused on user experience on the patient side, creating an ease of scheduling and having the capability to access medical assistance. Patients should be able to sort doctors' specialties based on their medical needs, and assemble their own healthcare teams. For example, one patient has atrocious eczema symptoms. She should be able to schedule a virtual appointment with available in-network doctors, and create a dermatology care team which comprises of herself as the patient, doctor, appointment time and other necessary care team's attributes. The patient has a certain ownership of her care team, resulting from the automated system in streamlining health provider workflow.  &lt;/p&gt;
&lt;h3&gt;
  
  
  2. API Searching Saga &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Once I envisioned the final outputs, the very next thing would be to acquire a list of doctors and their specialties. Being able to feed my application with this data allows new users (as patients) to sign up and have immediate capability to schedule appointments. API search can be fun and gnarly at the same time. I found success from other developers utilizing &lt;a href="https://developer.betterdoctor.com/"&gt;BetterDoctor API&lt;/a&gt;, and got really excited with their doctors and subsequent information. After spending a day on debugging sessions, I learned BetterDoctor API is officially deprecated. 😢&lt;br&gt;
Fret not! I moved on, spent another day searching for an Open API, and landed on &lt;a href="https://data.cms.gov/provider-data/dataset/mj5m-pzi6"&gt;Centers for Medicare and Medicaid Services&lt;/a&gt;. Their datasets are officially used on &lt;a href="https://www.medicare.gov/"&gt;Medicare.gov&lt;/a&gt;, and limited to eligible professionals (EPs) listed on Medicare Care Compare. As a result, I had to scratch out the &lt;code&gt;Healthcare Provider&lt;/code&gt; model from my original domain modeling. The rest of my models still meet the purpose of fulfilling MVP and lay the groundwork for my &lt;strong&gt;Content Management System (CMS)&lt;/strong&gt;. The datasets seed about 450+ healthcare professionals with varying specialties. I had to refresh my memory on how to parse JSON data from REST API from &lt;a href="https://dev.to/codinghall/api-cli-space-exploration-108f"&gt;my first capstone project&lt;/a&gt;. Thanks to Ruby gems &lt;a href="https://github.com/ruby/open-uri"&gt;OpenURI&lt;/a&gt; and &lt;a href="https://github.com/sparklemotion/nokogiri"&gt;Nokogiri&lt;/a&gt;, I successfully created my doctors collection in JSON format. I had to fudge a few doctors' attributes in order to execute model validations properly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JOB9cV-r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yqz7ahsm9vt214so6ttj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JOB9cV-r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yqz7ahsm9vt214so6ttj.gif" alt="Alt Text" width="600" height="183"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Creating Active Record Model &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Rails pre-dominantly identifies core components in &lt;strong&gt;MVC (Model-View-Controller)&lt;/strong&gt; paradigm. Most of the logic of object relationships, such as &lt;code&gt;patient&lt;/code&gt; has_many &lt;code&gt;doctors&lt;/code&gt;, reside in the &lt;strong&gt;Active Record models&lt;/strong&gt;. Controllers allow exposure of our database from these AR model associations and rendered views. This modular approach creates distinction of each MVC responsibility, which outlines the Rails architectural framework patterns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rails new plan-my-md-visit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Upon instantiation of the command prompt, Rails executes its conventional file system from &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt; to &lt;code&gt;Gemfile&lt;/code&gt;, and many more. There are 4 main models: &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Patient&lt;/code&gt;, &lt;code&gt;Doctor&lt;/code&gt; and &lt;code&gt;Healthcare Team&lt;/code&gt; with their model associations as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cWmrvQlo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/myyi8r0f32b1fsg9iche.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cWmrvQlo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/myyi8r0f32b1fsg9iche.jpg" alt="Alt Text" width="880" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;user &lt;code&gt;has_one&lt;/code&gt; :patient&lt;br&gt;
user &lt;code&gt;has_one&lt;/code&gt; :doctor&lt;/p&gt;

&lt;p&gt;patient &lt;code&gt;belongs_to&lt;/code&gt; :user &lt;br&gt;
patient &lt;code&gt;has_many&lt;/code&gt; :healthcare_teams&lt;br&gt;
patient &lt;code&gt;has_many&lt;/code&gt; :doctors, &lt;code&gt;through:&lt;/code&gt; :healthcare_teams&lt;/p&gt;

&lt;p&gt;healthcare_team &lt;code&gt;belongs_to&lt;/code&gt; :patient&lt;br&gt;
healthcare_team &lt;code&gt;belongs_to&lt;/code&gt; :doctor&lt;/p&gt;

&lt;p&gt;doctor &lt;code&gt;belongs_to&lt;/code&gt; :user&lt;br&gt;
doctor &lt;code&gt;has_many&lt;/code&gt; :healthcare_teams &lt;br&gt;
doctor &lt;code&gt;has_many&lt;/code&gt; :patients, through: healthcare_teams&lt;/p&gt;

&lt;p&gt;&lt;a href="https://guides.rubyonrails.org/generators.html"&gt;Rails Generators&lt;/a&gt; streamline the effort of setting up models and their table migrations.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rails g model Doctor user:references gender:string specialty:string hospital:string address:string city:string state:string zipcode:integer &lt;span class="nt"&gt;--no-test-framework&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similar implementations occurred in the other models. Following building the &lt;strong&gt;Active Record associations&lt;/strong&gt;, testing Rails models in &lt;code&gt;rails console&lt;/code&gt; is a necessity for quality control. I am pleased with my basic schema composition.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mi"&gt;2021_01_04_042023&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"firstname"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"lastname"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"username"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"email"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"password_digest"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt; &lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"patients"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"user_id"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"medical_record"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"test_results"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"medications"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"doctors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"user_id"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"gender"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"specialty"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"hospital"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"address"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"city"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"state"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"zipcode"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"healthcare_teams"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"patient_id"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"doctor_id"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"appointment"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"test_result"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"treatment_plans"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"prescriptions"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decimal&lt;/span&gt; &lt;span class="s2"&gt;"billing"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Validations protect our database, and I always think that it is wise to set validations early (prior to controllers and views). Other developers might think otherwise. I identified a few rudimentary &lt;strong&gt;Active Record Validations&lt;/strong&gt;, mainly to avoid seeding any bad data. Each user should be unique, and in most web applications, there should only be one particular username or email associated with the account. I have no angst towards Elon Musk's son named X Æ A-12, but my application currently only allows alphabetic letters.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; 
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;format: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;without: &lt;/span&gt;&lt;span class="sr"&gt;/[0-9]/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="s2"&gt;"Numbers are not allowed."&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;format: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;without: &lt;/span&gt;&lt;span class="sr"&gt;/[0-9]/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="s2"&gt;"Numbers are not allowed."&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Aside from model associations and validations, I implemented the &lt;a href="https://en.wikipedia.org/wiki/Law_of_Demeter"&gt;Law of Demeter&lt;/a&gt; design principle by adopting the "one dot" rule. For example, in order to retrieve doctor's fullname, the proper code would be &lt;code&gt;doctor.user.fullname&lt;/code&gt; following our model associations and their attributes. I encapsulated the logic in the &lt;code&gt;Doctor&lt;/code&gt; model, in reference to the object's user reference, and shortened the code to &lt;code&gt;doctor.fullname&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Doctor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fullname&lt;/span&gt; 
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fullname&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Active Record provides more! I found it extremely useful when implementing &lt;a href="https://guides.rubyonrails.org/active_record_querying.html"&gt;AREL (A Relational Algebra)&lt;/a&gt; in building optimized queries. It helped me in sorting out the intended outcomes of &lt;code&gt;doctors.json&lt;/code&gt; datasets with minimal time complexity. I was able to sort doctors' specialties with this query interface, &lt;code&gt;Doctor.select(:specialty).distinct.order(specialty: :asc)&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Action Controllers &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I took the liberty of developing overall user experience (as patients) with &lt;a href="https://www.figma.com/"&gt;Figma&lt;/a&gt;. My previous &lt;a href="https://trydesignlab.com/"&gt;Designlab's UX &amp;amp; UI courses&lt;/a&gt; proved to be useful when creating this basic mid-fidelity wireframing. The exercise helped me to map the different route helpers, HTTP verbs, paths and controller actions following RESTful design principles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IekAhOyc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4o3lgie540m4c7mspcw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IekAhOyc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4o3lgie540m4c7mspcw6.png" alt="Alt Text" width="880" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Users as Patients&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Upon signing up or logging in, the patient users have access to view their care teams. Overall mappings of the patient users as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sessions Controller&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Verb&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/signin&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;user logging in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;create&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/signin&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;user authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;destroy&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/logout&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;user logging out&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Users Controller&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Verb&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/users/new&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;render form for new user creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;create&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/users/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;create a new user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/users/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;show a single user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;edit&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/users/:id/edit&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;render the form for editing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;update&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/users/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;update a user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;destroy&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/users/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;delete a user&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Patients Controller&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Verb&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/new&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;render form for new patient creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;create&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;create a new user patient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;user patient main page&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Doctors Controller&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Verb&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;index&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/doctors&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;view doctors with specialty filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/doctors/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;show a single doctor information&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Healthcare Teams Controller&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Verb&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/select_specialty&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;user patient select doctor specialty&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Healthcare Teams Controller (nested resources)&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Verb&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;index&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:patient_id/healthcare_teams&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:patient_id/healthcare_teams/new&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:patient_id/healthcare_teams/new&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;create&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:patient_id/healthcare_teams/:id&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/patients/:patient_id/healthcare_teams/:id&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are restrictions for patient users, for instance updating doctor's profile information or viewing other patient users information. My app has to account for such intrusion. In the &lt;code&gt;Application Controller&lt;/code&gt;,  private methods &lt;code&gt;current_user&lt;/code&gt; and &lt;code&gt;current_patient&lt;/code&gt; were created to police this access policy. The two methods can be propagated on other controllers when granting certain privileges based on &lt;code&gt;current_user&lt;/code&gt;'s identity. The following is a &lt;code&gt;current_patient&lt;/code&gt; examples of a user.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PatientsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;

    &lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:current_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:current_patient&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;  
        &lt;span class="vi"&gt;@patient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Patient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@patient&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;current_patient&lt;/span&gt;
            &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:alert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Error URL path."&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;patient_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_patient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Users as Admins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The admin group should have the greatest privileges when performing &lt;strong&gt;Create, Read, Update and Delete (CRUD) functions&lt;/strong&gt; on &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Patient&lt;/code&gt;, &lt;code&gt;Doctor&lt;/code&gt; and &lt;code&gt;Healthcare Team&lt;/code&gt; models. Doctors might have the capability to update Care Team's attributes such as treatment plans, test results and medications. However, they are not allowed to update patient profiles as they are restricted to administrative access.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="c1"&gt;# Only Admin can see Users Lists&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  

  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:doctors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 

  &lt;span class="c1"&gt;# Admin privileges&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:patients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:doctors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:healthcare_teams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The application of &lt;strong&gt;namespace routes&lt;/strong&gt; shortened my overall scoping routes, wrapping &lt;code&gt;/users&lt;/code&gt;, &lt;code&gt;/patients&lt;/code&gt;, &lt;code&gt;/doctors&lt;/code&gt; and &lt;code&gt;/healthcare_teams&lt;/code&gt; resources under &lt;code&gt;/admin&lt;/code&gt;. One finicky note on &lt;code&gt;destroy&lt;/code&gt; action. A user is either a patient or a doctor. When deleting a user, their subsequent patient or doctor information should also be deleted from our database.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin::UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="vi"&gt;@patient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;patient&lt;/span&gt; 
        &lt;span class="vi"&gt;@doctor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doctor&lt;/span&gt; 

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vi"&gt;@patient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
            &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
            &lt;span class="vi"&gt;@patient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
            &lt;span class="vi"&gt;@doctor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 

        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:notice&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"User deleted."&lt;/span&gt;
        &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;admin_users_path&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  5. Authentication and Authorization Terms &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;For standard user authentication (including signup, login and logout), I utilized Ruby gem &lt;code&gt;bcrypt&lt;/code&gt; and Active Record's &lt;a href="https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html"&gt;Secure Password&lt;/a&gt; class methods. &lt;code&gt;has_secure_password&lt;/code&gt; needs to be included in the &lt;code&gt;User&lt;/code&gt; model. This implementation provides methods to set and authenticate user's password, following users' table and &lt;code&gt;password_digest&lt;/code&gt; attribute. &lt;/p&gt;

&lt;p&gt;I challenged myself to set two authentication providers alongside the traditional username and password set up. Ruby gem &lt;code&gt;omniauth&lt;/code&gt; provides a gateway to utilizing &lt;em&gt;multi-provider&lt;/em&gt; authentication strategies. While &lt;a href="https://github.com/omniauth/omniauth"&gt;GitHub&lt;/a&gt; relies on gem &lt;code&gt;omniauth-github&lt;/code&gt;, &lt;a href="https://developers.google.com/identity/protocols/oauth2"&gt;Google&lt;/a&gt; depends on gem &lt;code&gt;omniauth-google-oauth2&lt;/code&gt;. Gem &lt;code&gt;dotenv-rails&lt;/code&gt; is required to securely save &lt;code&gt;PROVIDER_CLIENT_ID&lt;/code&gt; and &lt;code&gt;PROVIDER_SECRET&lt;/code&gt;. I defined the Rack Middleware in Rails initializer at &lt;code&gt;config/initializers/omniauth.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt; &lt;span class="no"&gt;OmniAuth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Builder&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="ss"&gt;:developer&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;production?&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="ss"&gt;:github&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GITHUB_KEY'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GITHUB_SECRET'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="ss"&gt;:google_oauth2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GOOGLE_KEY"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GOOGLE_SECRET"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;skip_jwt: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the &lt;code&gt;config/routes.rb&lt;/code&gt; file, the callback routes &lt;code&gt;get '/auth/:provider/callback', to: 'sessions#omniauth'&lt;/code&gt; consolidates both providers (GitHub and Google). The results of authentication hash available in the callback vary from each provider. Two class methods, &lt;code&gt;find_or_create_by_google(auth)&lt;/code&gt; and &lt;code&gt;find_or_create_by_github(auth)&lt;/code&gt;, are provided in the &lt;code&gt;User&lt;/code&gt; model and invoked in the &lt;code&gt;Sessions Controller&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SessionsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;omniauth&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;auth_hash&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;auth_hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"google_oauth2"&lt;/span&gt;
            &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_or_create_by_google&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;auth_hash&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;auth_hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"github"&lt;/span&gt;
            &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_or_create_by_github&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 

        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
        &lt;span class="vi"&gt;@current_patient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Patient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_or_create_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="kp"&gt;private&lt;/span&gt; 

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'omniauth.auth'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  6. Action Views &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The part that requires the least amount of code, and User Interface as its focal point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forms forms forms!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Through Flatiron School curriculums, I became well-versed with &lt;code&gt;form_for&lt;/code&gt; &lt;a href="https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html"&gt;FormBuilder&lt;/a&gt; features for models associated with Active Record models, and &lt;code&gt;form_tag&lt;/code&gt; for manual route passing where form params will be submitted. For this project, I decided to put &lt;code&gt;form_with&lt;/code&gt; into service. It was introduced in Rails 5.1, and the idea is to merge both implementations of &lt;code&gt;form_tag&lt;/code&gt; and &lt;code&gt;form_for&lt;/code&gt;. I might as well get comfortable with &lt;a href="https://api.rubyonrails.org/v6.1.0/classes/ActionView/Helpers/FormHelper.html#method-i-form_with"&gt;form_with&lt;/a&gt; view helpers and its lexical environment. At first, I was not able to display error messages, and discovered I had to add &lt;code&gt;local: true&lt;/code&gt; syntax. Below is a snippet of my &lt;code&gt;/admin/healthcare_teams/:id/edit&lt;/code&gt; route. Note on the syntax format on the nested resource, &lt;code&gt;[:admin, @healthcare_team]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= render partial: '/errors', locals: { record: @healthcare_team } %&amp;gt;

&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_with&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@healthcare_team&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;local: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="sx"&gt;%&amp;gt;
   &amp;lt;%= f.label :appointment, "Appointment" %&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= f.datetime_field :appointment %&amp;gt;

   &amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:test_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Test Result"&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= f.text_area :test_result %&amp;gt;

   &amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:treatment_plans&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Treatment Plans"&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= f.text_area :treatment_plans %&amp;gt;

   &amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:prescriptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Prescriptions"&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= f.text_area :prescriptions %&amp;gt;

   &amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:billing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Billing"&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= f.number_field :billing, min: 0, step: 0.01 %&amp;gt;

   &amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s2"&gt;"Update Care Team"&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;% end &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While Rails' doctrine is pursuant to &lt;strong&gt;convention over configuration&lt;/strong&gt;, I had to customize one route &lt;code&gt;get '/select_specialty', to: 'healthcare_teams#select_specialty'&lt;/code&gt;. I want the patient users to have the ability to sort doctors by specialty when scheduling appointments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r3hkguGq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9y29o8dpocm976cv7hpq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r3hkguGq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9y29o8dpocm976cv7hpq.gif" alt="Alt Text" width="600" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS - Oh My!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While it was all fun in rendering many views in order to make my app more interactive, I found myself spending a tremendous amount of time on CSS clean-ups. I am thankful for &lt;a href="https://materializecss.com/"&gt;MaterializeCSS&lt;/a&gt;, and its built-in &lt;code&gt;scss&lt;/code&gt; and &lt;code&gt;jquery&lt;/code&gt;. Though, it gave me a lot of headache with debugging and reading Stack Overflow especially when implementing their CSS &lt;code&gt;classes&lt;/code&gt; onto &lt;code&gt;forms&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt; and &lt;code&gt;button&lt;/code&gt; elements. I have no CSS experience, and maybe it's about time to educate myself further via Udemy courses.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0cRPsyLgx88"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Lastly, as always — Lessons Learned &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;My struggle on this project started off when designing the overall user flow, either as patients or doctors. It was an ambitious idea at first, trying to figure out both users simultaneously. My interim cohort leader, Eriberto Guzman, suggested to focus on developing my project from the patient users point of view, and refine for other user groups as my project progresses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5xAVP500--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2p6jp65lypz7m05ntsgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5xAVP500--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2p6jp65lypz7m05ntsgn.png" alt="Alt Text" width="880" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My preliminary &lt;strong&gt;Entity Relationship Diagram (ERD)&lt;/strong&gt; had a flaw in the &lt;code&gt;User&lt;/code&gt; model associations. User &lt;code&gt;has_many&lt;/code&gt; patients, and user &lt;code&gt;has_many&lt;/code&gt; doctors. I realized this during debugging sessions when setting up &lt;code&gt;Admin&lt;/code&gt; controllers that I had to refactor the user either as a patient or a doctor. I was relieved to find the only difference on the associations methods was minimal. For example, &lt;code&gt;self.patients.build&lt;/code&gt; is one of the methods for &lt;code&gt;has_many&lt;/code&gt; association, and it was revised to &lt;code&gt;self.build_patient&lt;/code&gt; when &lt;code&gt;has_one&lt;/code&gt; was declared.&lt;/p&gt;

&lt;p&gt;Refactoring codes will always be a perpetual exercise as a developer. I plan on going back, and restructuring any vulnerabilities residing in my code - but first, need to deploy on Heroku and submit this project for my upcoming project assessment. So long Rails.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fentybit"&gt;
        fentybit
      &lt;/a&gt; / &lt;a href="https://github.com/fentybit/PlanMyMDVisit"&gt;
        PlanMyMDVisit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The MVP of Plan My MD Visit app is to create a virtual patient system where the automation benefits patient 24/7 seeking virtual medical assistance, improving overall patient well-being. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Plan My MD Visit&lt;/h1&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fentybit/PlanMyMDVisitapp/assets/images/readme_main.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YPYjDxsf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/fentybit/PlanMyMDVisitapp/assets/images/readme_main.gif"&gt;&lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Domain Modeling :: Virtual Healthcare&lt;/strong&gt;&lt;br&gt;
Welcome to my simplistic version of Virtual Healthcare system.&lt;br&gt;
The automation benefits patients 24/7 seeking medical assistance, improving overall patient well-being!&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/0cRPsyLgx88" rel="nofollow"&gt;YouTube Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://dev.to/fentybit/plan-my-md-visit-c0l" rel="nofollow"&gt;DEV Blog&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
About&lt;/h2&gt;
&lt;p&gt;The pandemic that has been lingering all around us since early 2020 has caused an apparent challenge to the current healthcare system. It is a testament to the new modern demand of digital healthcare. The conventional healthcare system is currently overflown with predominantly Covid-19 patients, exceeding their abilities to facilitate care of other medical patient needs.&lt;/p&gt;
&lt;p&gt;The Minimum Viable Product (MVP) of Plan My MD Visit app is to create a virtual patient system where the automation benefits patient 24/7 seeking virtual medical assistance, improving overall patient well-being. My application carries essential features and minimal attributes of tele-health platforms. Patients make their visits to the clinic, laboratory or hospital only when necessary and/or advised by…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fentybit/PlanMyMDVisit"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;Post Scriptum:&lt;br&gt;
This is my Module 3 capstone project with Flatiron School. I believe one of the catalyst to becoming a good programmer is to welcome constructive criticism. Feel free to drop a message. 🙂&lt;/p&gt;

&lt;p&gt;Keep Calm, and Code On.&lt;/p&gt;

&lt;p&gt;External Sources:&lt;br&gt;
&lt;a href="https://data.cms.gov/provider-data/dataset/mj5m-pzi6"&gt;Centers for Medicare and Medicaid Services&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/excid3/simple_calendar"&gt;Simple Calendar&lt;/a&gt;&lt;br&gt;
&lt;a href="https://materializecss.com/"&gt;MaterializeCSS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/swlh/google-authentication-strategy-for-rails-5-application-cd37947d2b1b"&gt;Google Authentication Strategy for Rails 5 Application&lt;/a&gt;&lt;/p&gt;






&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>css</category>
    </item>
    <item>
      <title>Rails Intro::Mandalorian</title>
      <dc:creator>fentybit</dc:creator>
      <pubDate>Sat, 12 Dec 2020 21:42:29 +0000</pubDate>
      <link>https://forem.com/fentybit/rails-intro-mandalorian-1ppp</link>
      <guid>https://forem.com/fentybit/rails-intro-mandalorian-1ppp</guid>
      <description>&lt;p&gt;Happy &lt;em&gt;belated&lt;/em&gt; Thanksgiving 🦃 and Merry &lt;em&gt;almost&lt;/em&gt; Christmas 🎄, fellow devs! &lt;/p&gt;

&lt;p&gt;I still can not believe that I am officially on Module 3! So glad that I passed my &lt;a href="https://dev.to/codinghall/sinatra-x-street-fighter-1hgl"&gt;Sinatra x Street Fighter&lt;/a&gt; project assessment, and enjoyed some downtime over Thanksgiving weekend. &lt;/p&gt;

&lt;p&gt;The past few weeks of my first exposure to Rails just blew my mind... &lt;a href="https://en.wikipedia.org/wiki/David_Heinemeier_Hansson"&gt;David H. Hansson&lt;/a&gt; created this magic of Rails, eliminating a bunch of repetitive Sinatra configuration. &lt;strong&gt;Ruby on Rails&lt;/strong&gt; is a web framework with tremendous open source contributions, and provides developers building applications with strong base frame functionality. Rails' architecture still relies upon the &lt;strong&gt;MVC (Model-View-Controller)&lt;/strong&gt; paradigm. The &lt;em&gt;separation of concerns&lt;/em&gt; governs the overall Rails file directory structure. Once the command &lt;code&gt;rails new &amp;lt;application_name&amp;gt;&lt;/code&gt; is prompted, new directories emerge including &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;, &lt;code&gt;lib&lt;/code&gt;, &lt;code&gt;Gemfile&lt;/code&gt; and so on. &lt;a href="https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application"&gt;You may review each directory and its functionality here&lt;/a&gt;. &lt;code&gt;rails s&lt;/code&gt; is a basic command line in order to start the &lt;em&gt;Rails server&lt;/em&gt;, while &lt;code&gt;rails c&lt;/code&gt; provides &lt;em&gt;Rails console&lt;/em&gt; session (similar to &lt;code&gt;rake console&lt;/code&gt;). One main characteristic from Rails I have learned thus far would be its &lt;strong&gt;&lt;em&gt;convention over configuration&lt;/em&gt;&lt;/strong&gt;. This pattern is inherent in the Rails routing system, file naming conventions and/or data flow structure. &lt;/p&gt;

&lt;p&gt;My case study focuses mainly on &lt;strong&gt;CRUD (Create, Read, Update and Delete)&lt;/strong&gt; Rails implementation, and it will be in reference to one of my favorite shows, &lt;strong&gt;The Mandalorian&lt;/strong&gt;. &lt;em&gt;"This is The Way."&lt;/em&gt; Season 2 is extraordinary! Kudos to &lt;a href="https://en.wikipedia.org/wiki/Jon_Favreau"&gt;Jon Favreau&lt;/a&gt; and our beloved Grogu. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FhuSSR6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.tenor.com/images/30523f960d5d67c0ef26283f441585f5/tenor.gif%3Fitemid%3D19358531" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FhuSSR6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.tenor.com/images/30523f960d5d67c0ef26283f441585f5/tenor.gif%3Fitemid%3D19358531" alt="https://media1.tenor.com/images/30523f960d5d67c0ef26283f441585f5/tenor.gif?itemid=19358531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rails Generators&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In Sinatra, we manually build many standard features. Rails, on the other hand, provides a more efficient way when building core application functionality. This exercise alone prevents spelling and syntax errors following &lt;strong&gt;RESTful (Representational State Transfer)&lt;/strong&gt; naming patterns. I adore the &lt;code&gt;rails generate&lt;/code&gt; (or &lt;code&gt;rails g&lt;/code&gt;) command line. It automatically populates our basic Rails app framework. There are a few &lt;a href="https://api.rubyonrails.org/classes/Rails/Generators.html"&gt;&lt;strong&gt;Rails generators&lt;/strong&gt;&lt;/a&gt; including &lt;em&gt;migration, model, controller, resource and scaffold&lt;/em&gt;. Each generator is capable of creating a large number of files and codes. This case study will utilize my favorite one, &lt;strong&gt;resource generator&lt;/strong&gt;. It creates some of the basic core functionality without code overflow. Let's create our first &lt;code&gt;resource&lt;/code&gt;, &lt;strong&gt;Mandalorian&lt;/strong&gt;, on the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; rails g resource Mandalorian name:string spaceship:string companion:string --no-test-framework
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--no-test-framework flag&lt;/code&gt; is being utilized as my case study will not dive in to any testing frameworks. The above command line gives us the following list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; invoke  active_record
&amp;gt; create    db/migrate/20201201211632_create_mandalorians.rb
&amp;gt; create    app/models/mandalorian.rb
&amp;gt; invoke  controller
&amp;gt; create    app/controllers/mandalorians_controller.rb
&amp;gt; invoke    erb
&amp;gt; create      app/views/mandalorians
&amp;gt; invoke    helper
&amp;gt; create      app/helpers/mandalorians_helper.rb
&amp;gt; invoke    assets
&amp;gt; invoke      scss
&amp;gt; create        app/assets/stylesheets/mandalorians.scss
&amp;gt; invoke  resource_route
&amp;gt; route    resources :mandalorians
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isn't Rails magic?!&lt;br&gt;
Let's take a peek at some of these files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# db/migrate/20201201211632_create_mandalorians.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateMandalorians&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:mandalorians&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:spaceship&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:companion&lt;/span&gt;

      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a new database table &lt;code&gt;mandalorians&lt;/code&gt; created under folder &lt;code&gt;db/migrate&lt;/code&gt; along with the assigned string attributes, &lt;code&gt;spaceship&lt;/code&gt; and &lt;code&gt;companion&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/application_record.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationRecord&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abstract_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# app/models/mandalorian.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Mandalorian&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# app/controllers/mandalorians_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MandaloriansController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Mandalorian&lt;/code&gt; model directly inherits the Active Record values from &lt;code&gt;ApplicationRecord&lt;/code&gt;. The  &lt;code&gt;MandaloriansController&lt;/code&gt; currently does not have any single actions. &lt;em&gt;Resource generator&lt;/em&gt; allows flexibility when adding &lt;em&gt;necessary features&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;

&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:mandalorians&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A full &lt;code&gt;resources&lt;/code&gt; call currently resides in the &lt;code&gt;config/routes.rb&lt;/code&gt; file. &lt;code&gt;resources :mandalorians&lt;/code&gt; embodies the conventional RESTful routes in order to perform CRUD functions: &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt;. These routes will be adjusted as we progress on this case study.&lt;/p&gt;

&lt;p&gt;I will create our second &lt;code&gt;resource&lt;/code&gt;, &lt;strong&gt;Armor&lt;/strong&gt; in order to establish basic object relationships, &lt;code&gt;has_many&lt;/code&gt; and &lt;code&gt;belongs_to&lt;/code&gt;. Similar Rails file structure will be created upon instantiation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; rails g resource Armor name:string description:string --no-test-framework
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Models&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The models are still inheriting from the &lt;code&gt;ActiveRecord::Base&lt;/code&gt; class. &lt;strong&gt;Active Record&lt;/strong&gt; is a strong tool when implementing logic. It provides &lt;strong&gt;ORM (Object Relational Mapping)&lt;/strong&gt; meta-programming methods built into the models entity and associations. Model files may contain object relationships, validations, callbacks, custom scopes and/or others.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uKyY7_mB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/20lvgmimqz9sfaj4zig8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uKyY7_mB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/20lvgmimqz9sfaj4zig8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Active Record associations come into play especially when creating more complex data relationships. I would have to adjust both models, &lt;code&gt;Mandalorian&lt;/code&gt; and &lt;code&gt;Armor&lt;/code&gt;, along with the database migration. In the universe of my case study, let's assume that a mandalorian &lt;code&gt;has_many&lt;/code&gt; armors, and each armor &lt;code&gt;belongs_to&lt;/code&gt; a mandalorian. We understand the &lt;code&gt;armors&lt;/code&gt; table should include a &lt;code&gt;foreign key&lt;/code&gt; column, a reference to a primary key of the associated mandalorian.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/mandalorian.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Mandalorian&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:armors&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# app/models/armor.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Armor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:mandalorian&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;length: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;maximum: &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# db/schema.rb&lt;/span&gt;

&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mi"&gt;2020_12_01_221427&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"mandalorians"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"spaceship"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"companion"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"armors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"description"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"mandalorian_id"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Active Record validations&lt;/strong&gt; are useful in protecting the database from invalid data inputs. &lt;code&gt;validates&lt;/code&gt; method takes two arguments, &lt;code&gt;:name&lt;/code&gt; of the attribute requiring validation, and a hash of options to detail out how the validation works. &lt;code&gt;{ presence: true }&lt;/code&gt; prevents the &lt;code&gt;:name&lt;/code&gt; attribute from being empty. &lt;code&gt;{ uniqueness: true }&lt;/code&gt; does not allow identical &lt;code&gt;:name&lt;/code&gt; data input. &lt;/p&gt;

&lt;p&gt;It is always a good practice to test our models post migration (or, &lt;code&gt;rails db:migrate&lt;/code&gt;). Let's use my second favorite Rails console command line, &lt;code&gt;rails c&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mo"&gt;001&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mando&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mandalorian&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Din Djarin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;spaceship: &lt;/span&gt;&lt;span class="s2"&gt;"Razor Crest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;companion: &lt;/span&gt;&lt;span class="s2"&gt;"Grogu"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Mandalorian id: 1, name: "Din Djarin", spaceship: "Razor Crest", companion: "Grogu", created_at: "2020-12-02 01:11:33.083593", updated_at: "2020-12-02 01:11:33.083593"&amp;gt;&lt;/span&gt;

&lt;span class="mo"&gt;002&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;flamethrowers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mando&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;armors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Flamethrowers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s2"&gt;"Fire streams or bursts of fire"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Armor id: nil, name: "Flamethrowers", description: "Fire streams or bursts of fire", mandalorian_id: 1, created_at: nil, updated_at: nil&amp;gt;&lt;/span&gt;

&lt;span class="mo"&gt;003&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;flamethrowers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt; 
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Flamethrowers"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Fire streams or bursts of fire"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mandalorian_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2020-12-02 01:20:57.923623"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2020-12-02 01:20:57.923623"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am able to &lt;code&gt;create&lt;/code&gt; mando from Mandalorian class, with its spaceship and companion attributes. &lt;code&gt;build&lt;/code&gt; method is similar to &lt;code&gt;new&lt;/code&gt; method. &lt;code&gt;mando&lt;/code&gt; obviously has many &lt;code&gt;armors&lt;/code&gt;, and &lt;code&gt;build&lt;/code&gt; method is one of the association macros. Once &lt;code&gt;flamethrowers&lt;/code&gt; saved, Active Record automatically assigns it to &lt;code&gt;mando&lt;/code&gt;, or equivalently, &lt;code&gt;mandalorian_id = 1&lt;/code&gt;. Terrific! Our object relationships work. &lt;/p&gt;

&lt;p&gt;There are a lot of more &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html"&gt;class methods in Rails application&lt;/a&gt; aside from my rudimentary case study such as &lt;code&gt;has_many :through&lt;/code&gt;, &lt;code&gt;has_one&lt;/code&gt; and many more.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Controllers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Controllers essentially connect the models, views and routes. They inherit a number of methods built into the Rails controller system through &lt;code&gt;ApplicationController&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--82-LMdn9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://fastly.syfy.com/sites/syfy/files/styles/1400xauto/public/baby-yoda-carry.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--82-LMdn9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://fastly.syfy.com/sites/syfy/files/styles/1400xauto/public/baby-yoda-carry.gif" alt="https://fastly.syfy.com/sites/syfy/files/styles/1400xauto/public/baby-yoda-carry.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assuming following conventional mappings of full &lt;code&gt;resources&lt;/code&gt;, the &lt;code&gt;MandaloriansController&lt;/code&gt; has HTTP verbs, methods, paths and descriptions as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;HTTP verb&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Method&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Path&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;index&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;show all mandalorians&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;create&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;create a new mandalorian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians/new&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;render the form for new creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;edit&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians/:id/edit&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;render the form for editing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;show a single mandalorian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;update&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;update a new mandalorian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;destroy&lt;/td&gt;
&lt;td&gt;&lt;em&gt;/mandalorians/:id&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;delete a mandalorian&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;ArmorsController&lt;/code&gt; has similar mappings as above. &lt;/p&gt;

&lt;p&gt;These controller actions (or methods) will perform CRUD functions and render views to the end user. The &lt;code&gt;/:id&lt;/code&gt; on the url paths accepts &lt;code&gt;params[:id]&lt;/code&gt; passed to the route. This &lt;code&gt;dynamic routing system&lt;/code&gt; allows our controller methods to receive params input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;

&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:mandalorians&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;# get '/mandalorians', to: 'mandalorians#new'&lt;/span&gt;
  &lt;span class="c1"&gt;# post '/mandalorians', to: 'mandalorians#create'&lt;/span&gt;
  &lt;span class="c1"&gt;# get '/mandalorians/:id', to: 'mandalorians#show'&lt;/span&gt;
  &lt;span class="c1"&gt;# get '/mandalorians/:id/edit', to: 'mandalorians#edit'&lt;/span&gt;
  &lt;span class="c1"&gt;# patch '/mandalorians/:id', to: 'mandalorians#update'&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:armors&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Sinatra application, the actions' routes reside in the controller. Rails assigns routes in the &lt;code&gt;config/routes.rb&lt;/code&gt; by default, and elaborate the actions as methods in the controllers' files. &lt;code&gt;resources :mandalorians, only: [:new, :show, :edit]&lt;/code&gt; strictly only allows new, show and edit routing system. Note: I revised previously full path &lt;code&gt;resources&lt;/code&gt; down to three &lt;code&gt;methods&lt;/code&gt;. On the other hand, &lt;code&gt;resources :armors&lt;/code&gt; provides a full set of routing systems; &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Since validations were implemented in the models, the controllers require slight modifications to the &lt;code&gt;create&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; actions. Ideally if validations were to fail, the form needs to be re-rendered. For example, the &lt;code&gt;:new&lt;/code&gt; form params input fails the Active Record validation. &lt;code&gt;:new&lt;/code&gt; template would have to be re-rendered. Similar to the &lt;code&gt;:edit&lt;/code&gt; form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/mandalorians_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MandaloriansController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
    &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_mandalorian&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt; 
        &lt;span class="vi"&gt;@mandalorian&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mandalorian&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt; 
        &lt;span class="vi"&gt;@mandalorian&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mandalorian&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mandalorian_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@mandalorian&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt; 
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@mandalorian&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; 
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt; 
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt; 
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@mandalorian&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mandalorian_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@mandalorian&lt;/span&gt; 
        &lt;span class="k"&gt;else&lt;/span&gt;  
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt; 
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="kp"&gt;private&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_mandalorian&lt;/span&gt; 
        &lt;span class="vi"&gt;@mandalorian&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mandalorian&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mandalorian_params&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:mandalorian&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:spaceship&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:companion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;before_action :set_mandalorian&lt;/code&gt; helps in keeping our code &lt;strong&gt;DRY (Don't Repeat Yourself)&lt;/strong&gt;. It triggers the &lt;code&gt;set_mandalorian&lt;/code&gt; function at the instantiation of &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; actions. Each action requires an object instance of Mandalorian class through &lt;code&gt;.find(params[:id])&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html"&gt;URL or Route Helpers&lt;/a&gt;&lt;/strong&gt; are another level of abstraction in Rails in order to avoid hard-coded paths. You can implement these route helpers on Controllers and Views files, but not in Models. It also provides more assistance to readability. For example, &lt;code&gt;"mandalorian_path(@mandalorian)"&lt;/code&gt; would be the &lt;em&gt;route helper&lt;/em&gt; version of &lt;code&gt;"/mandalorians/#{@mandalorian.id}"&lt;/code&gt;. &lt;code&gt;ActionView&lt;/code&gt;, a sub-gem of Rails, helps us in providing these numerous helper methods. In fact, let's implement another level of abstraction. &lt;code&gt;@mandalorian&lt;/code&gt; is applicable and a more succinct version of &lt;code&gt;"mandalorian_path(@mandalorian)"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The goal of &lt;strong&gt;strong params&lt;/strong&gt; is to whitelist the parameters received. In the &lt;code&gt;mandalorian_params&lt;/code&gt; function, the &lt;code&gt;require&lt;/code&gt; method &lt;strong&gt;must&lt;/strong&gt; require a key called &lt;code&gt;:mandalorian&lt;/code&gt;. The &lt;code&gt;permit&lt;/code&gt; method allows more flexibility in key attributes, and is especially useful when assigning mass attributes.  &lt;/p&gt;

&lt;p&gt;On a side note, I found &lt;code&gt;raise params.inspect&lt;/code&gt; as a great way to print &lt;code&gt;params&lt;/code&gt; when working in between both controllers and views. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Views&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;View files should have the least amount of logic, and their solid purpose is to render views for the end user. In this exercise, we will only focus on &lt;strong&gt;implicit rendering&lt;/strong&gt; following Rails convention. My application instinctively seeks out view files carrying the same name as the controller actions. Each action from the controller corresponds only to its respective view. For example, &lt;code&gt;new&lt;/code&gt; action only communicates with &lt;code&gt;new.html.erb&lt;/code&gt;. Any &lt;code&gt;instance variables&lt;/code&gt; from &lt;code&gt;new&lt;/code&gt; action only transcribes to &lt;code&gt;new.html.erb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46bagIiK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/clozw3j514ld7d84ucc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46bagIiK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/clozw3j514ld7d84ucc2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rails forms allow the end user to submit data into form fields. I will directly implement the forms using &lt;em&gt;Rails Route Helpers&lt;/em&gt; in lieu of plain HTML format, and &lt;code&gt;form_for&lt;/code&gt; in lieu of &lt;code&gt;form_tag&lt;/code&gt;. &lt;a href="https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html"&gt;form_for&lt;/a&gt; yields &lt;a href="https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html"&gt;FormBuilder&lt;/a&gt; object, and is full of convenient features. It is best implemented when forms are directly connected with the models, in performing CRUD functions. However, it is also crucial to understand the rudimentary &lt;a href="https://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html"&gt;application of &lt;code&gt;form_tag&lt;/code&gt; and its helper methods&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;form_authenticity_token&lt;/code&gt; helper is a part of Rails to combat &lt;strong&gt;CSRF (Cross-Site Request Forgery)&lt;/strong&gt;. CSRF general flow is one site implementing a request to another site without end user's consent. Fun fact, this &lt;code&gt;hidden_field_tag&lt;/code&gt; is a redundancy as Rails forms by default generates a required authenticity token. It reminds me of Sinatra manual implementation of assigning &lt;code&gt;session[:user_id] = @user.id&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;# app/views/mandalorians/_form.html.erb 

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;form_for&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor.errors.any&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"error_explanation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;pluralize&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;armor.errors.count&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
                prohibited this armor from being saved:
            &lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor.errors.full_messages.each&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;f.label&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;Name:&lt;/span&gt;&lt;span class="err"&gt;"%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;f.text_field&lt;/span&gt; &lt;span class="na"&gt;:name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;f.label&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;Description:&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;f.text_field&lt;/span&gt; &lt;span class="na"&gt;:description&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;hidden_field_tag&lt;/span&gt; &lt;span class="na"&gt;:authenticity_token&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;form_authenticity_token&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;f.submit&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

# app/views/mandalorians/new.html.erb

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;New Form&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;form&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;link_to&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;Back&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="na"&gt;armors_path&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 

# app/views/mandalorians/edit.html.erb

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Edit Form&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;form&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;link_to&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;Show&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;link_to&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;Back&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="na"&gt;armors_path&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since both &lt;code&gt;:new&lt;/code&gt; and &lt;code&gt;:edit&lt;/code&gt; are almost identical, I created &lt;code&gt;_form.html.erb&lt;/code&gt; where &lt;code&gt;form_for&lt;/code&gt; codes reside. &lt;code&gt;new.html.erb&lt;/code&gt; and &lt;code&gt;edit.html.erb&lt;/code&gt; render files to retrieve codes from &lt;code&gt;_form.html.erb&lt;/code&gt;. &lt;code&gt;form_for&lt;/code&gt; automatically sets up the path where the form will be sent.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;errors.full_messages&lt;/code&gt; is optional, but &lt;a href="https://guides.rubyonrails.org/active_record_validations.html#displaying-validation-errors-in-views"&gt;displaying validation errors in views&lt;/a&gt; has proved to enhance user experience. Being able to notify users of input errors creates stability in the database. It is most prudent for views to display errors to the user. When the form (either &lt;code&gt;:new&lt;/code&gt; or &lt;code&gt;:edit&lt;/code&gt;) is re-rendered, pre-filling forms with existing user inputs promotes better user experience. None of us wants the hassle of re-typing or re-filling pre-populated forms. &lt;code&gt;form_for&lt;/code&gt; automatically &lt;strong&gt;pre-populates&lt;/strong&gt; form reload with pre-existing values of &lt;code&gt;@mandalorian&lt;/code&gt; data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u8003GaZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c1c7pi2fs35zb0u0d3z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u8003GaZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c1c7pi2fs35zb0u0d3z2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the view renders an edit form and once reloaded, the model executes an error message that &lt;code&gt;Name has already been taken&lt;/code&gt; from the Active Record validation, &lt;code&gt;validates :name, uniqueness: true&lt;/code&gt;. &lt;code&gt;form_for&lt;/code&gt; realizes that the current &lt;code&gt;@mandalorian&lt;/code&gt; is &lt;em&gt;not a new instance&lt;/em&gt; of the Mandalorian class.  &lt;/p&gt;

&lt;p&gt;I would hate to delete any of our bounty hunters, let's try to implement the &lt;code&gt;delete&lt;/code&gt; request on our Armor model. HTML5 forms officially do not support &lt;code&gt;delete&lt;/code&gt; and &lt;code&gt;patch&lt;/code&gt; methods. We place the &lt;code&gt;delete&lt;/code&gt; request in the &lt;code&gt;armors_controller&lt;/code&gt;, and render the &lt;code&gt;delete&lt;/code&gt; button on &lt;code&gt;show.html.erb&lt;/code&gt;. Once deleted, the end user will be routed to armors index view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/armors_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt; 
    &lt;span class="vi"&gt;@armor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Armor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="vi"&gt;@armor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt; 
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;armors_path&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;# app/views/armors/show.html.erb 

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Name: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor.name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Description: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor.description&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Mandalorian: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor.mandalorian.name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;button_to&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;Delete&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;armor&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;method:&lt;/span&gt; &lt;span class="na"&gt;:delete&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://api.rubyonrails.org/v5.1.7/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to"&gt;button_to&lt;/a&gt; is a better version of &lt;code&gt;link_to&lt;/code&gt; when sending a &lt;code&gt;delete&lt;/code&gt; request. &lt;/p&gt;

&lt;p&gt;In the previous Rails console, we assured our object relationships work. Similar model associations can be implemented in the view files. Since each armor &lt;code&gt;belongs_to&lt;/code&gt; a mandalorian, we should be able to call out &lt;code&gt;@armor.mandalorian.name&lt;/code&gt; method. I repeat. Isn't Rails magic?!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4eTiMEKH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.tenor.com/images/614de537ea516c274f9c95e722fbf9d5/tenor.gif%3Fitemid%3D15630699" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4eTiMEKH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.tenor.com/images/614de537ea516c274f9c95e722fbf9d5/tenor.gif%3Fitemid%3D15630699" alt="https://media1.tenor.com/images/614de537ea516c274f9c95e722fbf9d5/tenor.gif?itemid=15630699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is The Way.&lt;br&gt;
The Mandalorian&lt;/p&gt;
&lt;/blockquote&gt;






&lt;center&gt;
&lt;br&gt;
&lt;a href="https://fentybit.me/"&gt;&lt;strong&gt;fentybit&lt;/strong&gt;&lt;/a&gt; | &lt;a href="https://github.com/fentybit"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/fentybit"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/fentybit/"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>activerecord</category>
      <category>formbuilder</category>
    </item>
  </channel>
</rss>
