<?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>DEV Community: Naftali Kulik</title>
    <description>The latest articles on DEV Community by Naftali Kulik (@nkulik94).</description>
    <link>https://dev.to/nkulik94</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%2F853223%2Fa60de30b-9a39-449b-a9d0-1b9050673d1f.png</url>
      <title>DEV Community: Naftali Kulik</title>
      <link>https://dev.to/nkulik94</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nkulik94"/>
    <language>en</language>
    <item>
      <title>Using Active Model Serializer</title>
      <dc:creator>Naftali Kulik</dc:creator>
      <pubDate>Mon, 01 Aug 2022 18:14:00 +0000</pubDate>
      <link>https://dev.to/nkulik94/using-active-model-serializer-4ffg</link>
      <guid>https://dev.to/nkulik94/using-active-model-serializer-4ffg</guid>
      <description>&lt;h2&gt;
  
  
  Installing the Active Model Serializer gem
&lt;/h2&gt;

&lt;p&gt;In order to use Active Model Serializer, you will need to include it in your Gemfile. Simply add &lt;code&gt;gem "active_model_serializers"&lt;/code&gt; to your Gemfile and run &lt;code&gt;bundle install&lt;/code&gt;. Alternatively, you can run &lt;code&gt;bundle add active_model_serializers&lt;/code&gt; from the root directory of your app to accomplish the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serializer Basics
&lt;/h2&gt;

&lt;p&gt;As part of my ongoing journey toward becoming a full-stack developer, I have begun developing Rails API. Rails has many great built-in libraries to handle everything from organizing and modifying databases to setting up routes and controller actions to handle requests to those routes. However, using controller actions to handle the &lt;em&gt;data&lt;/em&gt; sent back in response to those requests has its limitations. The controller's job is to process the requests sent by the client, which includes but is not limited to authentication, authorization, updating the database in response to the contents of the request body, and actually sending the response. Using the controller to sort through the available data and decide what to send back would grow your controller actions into large, unwieldy, and difficult-to-read blocks of code.&lt;/p&gt;

&lt;p&gt;You may be wondering, who cares? Just send it all back and let the client sort it out! That's not too practical though. You may find yourself dealing with large databases with complex many-to-many relationships which require nested data to be sent to the client. Sending everything back in a large chunk for every request doesn't make much sense. Additionally, it may be possible that some of your controller actions require authorization, and if so there's a good chance there's also data that you only want available to authorized users. You wouldn't want, for example, &lt;code&gt;users#index&lt;/code&gt; to send all of your users' email addresses and phone numbers! That may be fine for other controller actions (for a hypothetical &lt;code&gt;User&lt;/code&gt; model) that require authorization, but not for one that's available for everyone.&lt;/p&gt;

&lt;p&gt;This is where &lt;code&gt;ActiveModel::Serializer&lt;/code&gt; comes in. The &lt;code&gt;acitve_model_serializer&lt;/code&gt; gem allows you to move all that code into a separate file, which will be accessed by the controller either implicitly (if the serializer shares the name of the model that it is connected to) or if explicitly specified. The serializer can be easily created with a rails generator, like this: &lt;code&gt;rails g serializer &amp;lt;serializer_name&amp;gt;&lt;/code&gt;. At its most basic, a serializer will include the table rows, as attributes, that are to be sent back in the response, something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

class UserSerializer &amp;lt; ActiveModel::Serializer
  attributes :id, :first_name, :last_name, :username, :bio, :avatar_url
end


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

&lt;/div&gt;

&lt;p&gt;This is telling the controller to &lt;em&gt;only&lt;/em&gt; include those attributes in the response. No sending the user's phone number to anyone who wants it! You can also define custom serializers. Let's say, using the above example, we wanted to send the user's full name as one string. we could write out a method that returns the full name, something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

def full_name
  "#{self.object.first_name} #{self.object.last_name}"
end


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

&lt;/div&gt;

&lt;p&gt;In this case, &lt;code&gt;self&lt;/code&gt; is the instance of UserSerializer, and &lt;code&gt;object&lt;/code&gt; is an attribute that allows you to access the current instance of &lt;code&gt;User&lt;/code&gt; that you are dealing with. By accessing the user, you can in turn access the data for that user and incorporate it into a method that returns whatever information that you want to be returned. Now all you have to do is add &lt;code&gt;:full_name&lt;/code&gt; to the list of attributes and it will be sent as part of the JSON data of the response.&lt;/p&gt;

&lt;p&gt;What about the example we used before, with certain controller actions which, upon authorization, send data such as personal user information back to the client? The serializer we have here doesn't send that information, which is good, but we do want the user to have access to it once they prove it's them. Our &lt;code&gt;users#show&lt;/code&gt; action, for example, may need to send the user their profile information, including information private to them. Our &lt;code&gt;create&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; actions, which allow the user to modify their profile, also need to return more detailed and personalized data.&lt;/p&gt;

&lt;p&gt;To accomplish this, we can generate a new serializer and explicitly specify in our controller to use this new one. We'll start with generating the new serializer: &lt;code&gt;rails g serializer user_profile&lt;/code&gt;. Now we can include the attributes we want to send, and specify in the controller to use this serializer, which might look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

render json: user, serializer: UserProfileSerializer


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

&lt;/div&gt;

&lt;p&gt;In this specific case, it might actually make more sense for the custom serializer to be used for the &lt;code&gt;index&lt;/code&gt; action, as that is the one that is apart from the others. In this case, we'd use &lt;code&gt;each_serializer&lt;/code&gt;, like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

render json: User.all, each_serializer: UserListSerializer


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

&lt;/div&gt;

&lt;p&gt;The most powerful use of serializers may be the ability to leverage Active Record associations to send nested data. In its most simple form, including associated data is as simple as sticking a &lt;code&gt;has_many&lt;/code&gt; (or whatever the relationship is) macro in the serializer (assuming the relationship is set up correctly in your models). You can even specify a separate serializer for the nested data if, and this is often going to be the case, the data you need to send as nested data is not necessarily what you'd want to send in response to a request to the nested resource itself. For example, a book &lt;code&gt;has_many&lt;/code&gt; many chapters. You may want to send some basic chapter information with the book (such as the names), but you don't necessarily need a comprehensive collection of information about the chapter, such as its word count, subject, etc, although you would want to send that in response to a request to &lt;code&gt;chapters&lt;/code&gt; itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Displaying Deeply Nested Data, My Way
&lt;/h2&gt;

&lt;p&gt;You can also send data that's nested even deeper, but that's a bit complicated and probably should be avoided if possible. I've found that often when I've felt like I wanted to nest data more than one layer deep, there was usually a better way to do it. Particularly, combining the features of custom serializers and Active Record associations can often get the results you need without resorting to writing complex code to send back complex data. Let's look at an example from my most recent project, &lt;a href="https://github.com/nkulik94/game-center" rel="noopener noreferrer"&gt;game-center&lt;/a&gt; (deployed &lt;a href="https://gamer-spot.herokuapp.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This app allows users to browse, like, rate, and review free online games (game information obtained via the Freetogame &lt;a href="https://www.freetogame.com/api-doc" rel="noopener noreferrer"&gt;API&lt;/a&gt;). The &lt;code&gt;Review&lt;/code&gt; model has some pretty complex associations. It &lt;code&gt;belongs_to&lt;/code&gt; a &lt;code&gt;User&lt;/code&gt; (which &lt;code&gt;has_many&lt;/code&gt; reviews), &lt;code&gt;belongs_to&lt;/code&gt; a &lt;code&gt;Game&lt;/code&gt; (which &lt;code&gt;has_many&lt;/code&gt; reviews, and &lt;code&gt;has_many&lt;/code&gt; users through reviews), and &lt;code&gt;belongs_to&lt;/code&gt; a &lt;code&gt;Rating&lt;/code&gt;. I'd like to be able to display a detailed game, which would include a list of reviews, along with some information about the user. A review from this list as displayed in the browser may look something like this:&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%2Fhpzza3r2t51djmdrd1v9.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%2Fhpzza3r2t51djmdrd1v9.png" alt="Sample Review"&gt;&lt;/a&gt;&lt;br&gt;
You may see the potential problem here. We need, in addition to the actual review content, information about the user (name, username, avatar) and the rating associated with this review. This is on top of the fact that the review itself is being sent as a nested resource! This could get complicated and impractical quickly. Allow me to demonstrate how a bit of creativity can make this quite simple.&lt;/p&gt;

&lt;p&gt;First, add &lt;code&gt;has_many :reviews&lt;/code&gt; to the &lt;code&gt;GameSerializer&lt;/code&gt;. This will send whichever attributes are specified in the &lt;code&gt;ReviewSerializer&lt;/code&gt;, &lt;em&gt;not including&lt;/em&gt; nested attributes, as a nested attribute of the &lt;code&gt;Game&lt;/code&gt;. Now we can use custom serializers and Active Record associations to customize our &lt;code&gt;Review&lt;/code&gt; objects as needed. Let's start with the basic attributes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

class ReviewSerializer &amp;lt; ActiveModel::Serializer
  attributes :id, :content
end


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

&lt;/div&gt;

&lt;p&gt;Assuming our client doesn't need access to the &lt;code&gt;game_id&lt;/code&gt; and &lt;code&gt;user_id&lt;/code&gt;, this is really all that needs to be sent back from the &lt;code&gt;Review&lt;/code&gt; model itself. We also want the rating, which, as we've mentioned before, is a separate resource that the review &lt;code&gt;belongs_to&lt;/code&gt;. Instead of trying to work out complicated nested attributes, let's let our association do the work for us in the form of a custom method:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

def rating
  self.object.rating.rating
end


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

&lt;/div&gt;

&lt;p&gt;Here we have &lt;code&gt;self.object&lt;/code&gt;, the review itself, &lt;code&gt;.rating&lt;/code&gt;, the instance of &lt;code&gt;Rating&lt;/code&gt; associated with this review, and &lt;code&gt;.rating&lt;/code&gt;, the attribute that has the actual value of the rating. In short, this method returns the value of the rating associated with this review, without resorting to sending nested and/or unnecessary data. Now we can just add &lt;code&gt;:rating&lt;/code&gt; to our list of attributes and there we have it! Now let's do the same for the user information that we need:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

def user_full_name
  "#{self.object.user.first_name} #{self.object.user.last_name}"
end

def user_username
  self.object.user.username
end

def user_avatar
  self.object.user.avatar_url
end

def user_tier
  self.object.user.tier
end


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

&lt;/div&gt;

&lt;p&gt;Let's see the whole serializer at once:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

class ReviewSerializer &amp;lt; ActiveModel::Serializer
  attributes :id, :game_id, :user_id, :content, :rating, :user_full_name, :user_username, :user_avatar, :user_tier

  def rating
    self.object.rating.rating
  end

  def user_full_name
    "#{self.object.user.first_name} #{self.object.user.last_name}"
  end

  def user_username
    self.object.user.username
  end

  def user_avatar
    self.object.user.avatar_url
  end

  def user_tier
    self.object.user.tier
  end
end


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

&lt;/div&gt;

&lt;p&gt;Now, the json response data for a game should look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
    "id": 19,
    "title": "Game Of Thrones Winter Is Coming",
    "thumbnail": "https://www.freetogame.com/g/340/thumbnail.jpg",
    "description": "Game of Thrones Winter is Coming is a free-to-play browser-based RTS based on the George R.R. Martin novels and popular HBO series. In the game developed by YOOZOOGames, player take on the role of a Westeros lord set on putting a stop to the wars between the Seven Kingdoms.\r\n\r\nThe game is built in Unity and offers players a balanced mix of strategy and RP. Players build bases, grow their kingdom, train armies, and recruit characters from the show, all while living within the story set forth in the TV series.",
    "game_url": "https://www.freetogame.com/open/game-of-thrones-winter-is-coming",
    "genre": "Strategy",
    "platform": "Web Browser",
    "publisher": "GTArcade",
    "developer": "YOOZOO Games ",
    "release_date": "2019-11-14",
    "likes": 4,
    "rating": "3.4",
    "reviews": [
        {
            "id": 602,
            "game_id": 19,
            "user_id": 6,
            "content": "Id quia ut. Quas a accusamus. Non iusto et.",
            "rating": 4,
            "user_full_name": "King Hamill",
            "user_username": "OldRasputinRussianImperialStout",
            "user_avatar": "https://robohash.org/eligendiquaevoluptas.png?size=300x300&amp;amp;set=set1",
            "user_tier": "Hall of Fame"
        },
        {
            "id": 1093,
            "game_id": 19,
            "user_id": 10,
            "content": "Qui ut doloribus. Sapiente ut odit. Nemo placeat sequi.",
            "rating": 3,
            "user_full_name": "Virgilio Larson",
            "user_username": "OrvalTrappistAle",
            "user_avatar": "https://robohash.org/ducimusrepudiandaeet.png?size=300x300&amp;amp;set=set1",
            "user_tier": "Hall of Fame"
        },
        {
            "id": 1197,
            "game_id": 19,
            "user_id": 11,
            "content": "Molestias veniam beatae. Ex alias ut. Mollitia quasi natus.",
            "rating": 5,
            "user_full_name": "Jackson Lamar",
            "user_username": "QB1",
            "user_avatar": "https://robohash.org/facereminimavoluptatem.png?size=300x300&amp;amp;set=set1",
            "user_tier": "Hall of Fame"
        }
    ]
}


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

&lt;/div&gt;

&lt;p&gt;There we go! Nice, simple, and organized!&lt;/p&gt;

&lt;p&gt;I have found that serializers can be an extremely powerful tool when used correctly, and I hope that I've demonstrated that here. Thanks for sticking around!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Ruby Bingo</title>
      <dc:creator>Naftali Kulik</dc:creator>
      <pubDate>Thu, 07 Jul 2022 19:02:00 +0000</pubDate>
      <link>https://dev.to/nkulik94/ruby-bingo-507h</link>
      <guid>https://dev.to/nkulik94/ruby-bingo-507h</guid>
      <description>&lt;p&gt;From the moment I started learning Ruby, I was able to see why so many programmers &lt;a href="https://www.ruby-lang.org/en/about/"&gt;love it&lt;/a&gt;. I found the syntax intuitive and easy to understand, and its flexibility allows for many different ways to accomplish similar things, allowing programmers to write their code in the way that's most comfortable for them. The syntax is often so simple that even someone with no programming experience whatsoever can often look at a block of code and have a pretty good idea of what's going on. Here's a quick example, taken from the project that I'll be discussing in a moment: It doesn't take a genius to figure out what &lt;code&gt;Board.generate_board until Board.all.count == 20&lt;/code&gt; is supposed to be doing, even if you don't have any knowledge of the code in the &lt;code&gt;generate_board&lt;/code&gt; method. In fact, Ruby's creator Yukihiro “Matz” Matsumoto said explicitly that "The goal of Ruby is to make programmers happy", and that goal shows in every aspect of the language.  &lt;/p&gt;

&lt;p&gt;Learning Ruby has also helped me develop a pretty good habit for programming in general. Ruby has so many built-in methods that memorizing them all is impractical and frankly a waste of time. Because of this, any time I am trying to accomplish a specific task the first thing I do is to Google if there already is an existing method for what I am trying to do (which there often is). Doing so allows me to avoid having to write unnecessarily complicated code, makes my code smoother and more readable, as well as expands my knowledge of the Ruby language in general. This habit has spilled over into my work with other programming languages, and I often find myself doing the same thing in JavaScript now. Although JS doesn't have quite as many built-in methods as Ruby, too often in the past I've stumbled on a method that would've saved me a lot of work in a previous project.&lt;/p&gt;

&lt;p&gt;My most recent project was a Bingo game, with a focus on backend development. (The repo for the backend is &lt;a href="https://github.com/nkulik94/phase-3-sinatra-react-project"&gt;here&lt;/a&gt;, and the frontend is &lt;a href="https://github.com/nkulik94/sinatra-react-bingo-frontend"&gt;here&lt;/a&gt;.) The frontend is a pretty basic React application, and the backend uses a SQLite database with the &lt;a href="https://guides.rubyonrails.org/active_record_basics.html"&gt;Active Record&lt;/a&gt; ORM, and &lt;a href="http://sinatrarb.com/"&gt;Sinatra&lt;/a&gt; to handle the routes.&lt;/p&gt;

&lt;p&gt;Here's a brief overview of what's relevant to this post. For a more detailed explanation of how the database and routes are set up see the &lt;a href="https://github.com/nkulik94/sinatra-react-bingo-frontend#readme"&gt;README&lt;/a&gt;. I'm going to be building out instance methods for the &lt;code&gt;PlayedBoards&lt;/code&gt; class, which is a model for a join table that establishes a many-to-many relationship between a &lt;code&gt;players&lt;/code&gt; table and a &lt;code&gt;boards&lt;/code&gt; table. Each &lt;code&gt;Player&lt;/code&gt; instance represents a user, each &lt;code&gt;Board&lt;/code&gt; represents a bingo board with a unique layout, and each &lt;code&gt;PlayedBoard&lt;/code&gt; contains all of the information relative to a specific player playing a specific board. The &lt;code&gt;PlayedBoard&lt;/code&gt; needs instance methods to handle the actual gameplay, as well as to simulate a complete game (for the seed file). I will be going through how we can build these methods, while (hopefully) sticking to good coding practices, such as the single-responsibility principle.&lt;/p&gt;

&lt;p&gt;The information that we will be working with is as follows. We have the layout of the board, obtained from the board via Active Record's &lt;code&gt;belongs_to:&lt;/code&gt; macro. This is stored as a string consisting of 25 random integers between 0 and 99, separated by spaces. It is in string form in order for it to be stored in the database, separated by spaces so it can easily be converted into an array using &lt;code&gt;.split(' ')&lt;/code&gt;. This is a useful trick I picked up online for storing arrays in a SQLite database. We also have a string from the &lt;code&gt;unused_numbers&lt;/code&gt; column of all numbers from 0 to 99. This will be used to pick numbers for the bingo game and modified as the game progresses so that no number is picked twice. Additionally, there are columns with integers representing the &lt;code&gt;turn_count&lt;/code&gt;, &lt;code&gt;turns_to_line&lt;/code&gt;, &lt;code&gt;turns_to_x&lt;/code&gt;, and &lt;code&gt;turns_to_full&lt;/code&gt;. These are to keep track of how many turns were needed to hit a particular milestone (line, x, full) to calculate the user's score. There is also a &lt;code&gt;filled_spaces&lt;/code&gt; string with the position on the board of any matching number, by index. Now let's write some code that will make it all work.&lt;/p&gt;

&lt;p&gt;Let's see what we need to do to make this work, in pseudocode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pick a number
remove that number from unused_spaces
increment turn_count
check board layout for match
if no match, end turn (for simulation, start next turn)
if match, add the index of the matching number to filled_spaces
check for a line (only if there isn't already)
if there is, update turns_to_line to current turn_count
check for x (only if there isn't already)
if there is, update turns_to_x to current turn_count
check if full
if it is, update turns_to_full to current turn_count (and end game in simulation)
end turn (in simulation start next turn if not full)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first step, picking a number, is handled by the frontend during gameplay. In the simulation it's as simple as passing &lt;code&gt;unused_nums.split(' ').sample&lt;/code&gt; into the &lt;code&gt;play_turn&lt;/code&gt; method, which is going to handle running all of the methods we are about to define. In fact, once all the methods handled by the &lt;code&gt;play_turn&lt;/code&gt; method were defined, all that needed to be done for the simulation was this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def sim_play
    play_turn(unused_nums.split(' ').sample) until is_full?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start making that &lt;code&gt;play_turn&lt;/code&gt; method work. First, let's remove our newly picked number from &lt;code&gt;unused_nums&lt;/code&gt; so it doesn't get picked again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def remove_from_unused num
    unused_nums_arr = self.unused_nums.split(' ')
    unused_nums_arr.delete num
    update(unused_nums: unused_nums_arr.join(' '))
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new number is passed as an argument to the &lt;code&gt;remove_from_unused&lt;/code&gt; method, which splits &lt;code&gt;unused_nums&lt;/code&gt; into an array, passes the picked number to Ruby's built-in &lt;code&gt;Array#delete&lt;/code&gt; method, and uses Active Record's &lt;code&gt;update&lt;/code&gt; method to send the new &lt;code&gt;unused_nums&lt;/code&gt; information back to the database. This doesn't interact with any other methods used to play a turn, so it is in fact the first line of our &lt;code&gt;play_turn&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def play_turn num
    remove_from_unused(num)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we have to increment the &lt;code&gt;turn_count&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def count_turn
    count = self.turn_count ? self.turn_count : 0
    update(turn_count: count + 1)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ternary is necessary because in this case, the default value for &lt;code&gt;turn_count&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;, so merely passing &lt;code&gt;self.turn_count + 1&lt;/code&gt; to the &lt;code&gt;update&lt;/code&gt; method wouldn't work for the first turn. This too can be added as is to the &lt;code&gt;play_turn&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def play_turn num
    remove_from_unused(num)
    count_turn
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have to find a match. Let's see what we can do here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def get_match num
    layout_arr = self.board.layout.split(' ')
    layout_arr.find_index num
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method accesses the layout from the board via the &lt;code&gt;belongs_to: :board&lt;/code&gt; macro and splits it into an array. It then uses Ruby's built-in &lt;code&gt;find_index&lt;/code&gt; method to find and return either the matched index of the layout array or &lt;code&gt;nil&lt;/code&gt; if no match is found. The return value of this method will be used to handle a potential match. The next line of our &lt;code&gt;play_turn&lt;/code&gt; method is ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; def play_turn num
     remove_from_unused(num)
     count_turn
     match = get_match(num)
     handle_match(match) if match
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line is a method we haven't defined yet which will take the index of the matched number and take care of updating what needs to be updated. If no match was found, the value of &lt;code&gt;match&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; and the turn ends with no further action. In the event of a match, the first thing we need to do is update the &lt;code&gt;filled_spaces&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def update_filled_spaces index
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    filled_spaces_arr.push(index)
    update(filled_spaces: filled_spaces_arr.join(' '))
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we split &lt;code&gt;filled_spaces&lt;/code&gt; into an array (or create an empty array if there haven't yet been any matches and the value of &lt;code&gt;filled_spaces&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;). We then add the index passed as an argument to the array and update the database. The first line of &lt;code&gt;handle_match&lt;/code&gt; is ready to be written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_match index
    update_filled_spaces(index)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will have to build out several methods to handle the rest. First, let's give ourselves a way of checking if the board has been filled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def is_full?
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    filled_spaces_arr.count == 25
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough! Now let's check if we have a line or an X. Our &lt;code&gt;Board&lt;/code&gt; class helpfully provides two class constants, &lt;code&gt;Board::LINE_WIN_COMBINATIONS&lt;/code&gt; and &lt;code&gt;Board::X_WIN&lt;/code&gt;. &lt;code&gt;Board::LINE_WIN_COMBINATIONS&lt;/code&gt; is an array containing other arrays, each containing the indexes of the layout needed to complete a specific line. &lt;code&gt;Board::X_WIN&lt;/code&gt; contains the indexes (indices? Dunno, according to Google either way works) needed to fill out an X on the board. Let's start with finding if there is an X:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def has_new_x?
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    !self.turns_to_x &amp;amp;&amp;amp; (Board::X_WIN - filled_spaces_arr).empty?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return true if two conditions are met. If the value for &lt;code&gt;turns_to_x&lt;/code&gt; is truthy, that means the X has already been filled on a previous turn, and &lt;code&gt;has_new_x&lt;/code&gt; will return false because the X is not new. The right side of the AND expression takes advantage of an interesting feature of Ruby, which is that arrays can be subtracted from each other, and if all of the elements in the array being subtracted from exist in the array being subtracted, the return value will be an empty array. For example: &lt;code&gt;[1, 2] - [4, 1, 3, 2] == []&lt;/code&gt;. In this case, we are subtracting &lt;code&gt;filled_spaces_array&lt;/code&gt; from &lt;code&gt;Board::X_WIN&lt;/code&gt; and checking if the result is empty. The return value of &lt;code&gt;.empty?&lt;/code&gt; will help determine the return value of &lt;code&gt;has_x?&lt;/code&gt;. We'll do something similar for our next method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def has_new_line?
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    !self.turns_to_line &amp;amp;&amp;amp; Board::LINE_WIN_COMBINATIONS.find { |combo| (combo - filled_spaces_arr).empty? }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are iterating through &lt;code&gt;Board::LINE_WIN_COMBINATIONS&lt;/code&gt; and checking if a similar expression as the one we used for &lt;code&gt;has_x?&lt;/code&gt; returns true for any of the possible combinations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The elements of &lt;code&gt;Board::LINE_WIN_COMBINATIONS&lt;/code&gt; and &lt;code&gt;Board::X_WIN&lt;/code&gt; are represented as strings to avoid the complexities of dealing with two different data types&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let's define a method that will handle updating the database in the event of a match. We need to do two things here. We'll need to update this particular instance of &lt;code&gt;PlayedBoard&lt;/code&gt;, as well as check if the current user's score is better than the high score currently saved to the related instance of &lt;code&gt;Board&lt;/code&gt;. Let's start with defining a method for the high scores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def update_high_score high_score
    if !self.board[high_score] || turn_count &amp;lt; self.board[high_score]
        self.board[high_score] = turn_count
        self.board.save
    end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This takes a key for the &lt;code&gt;Board&lt;/code&gt; class (:full_high_score, :x_high_score, or :line_high_score) as an argument and first checks if there is already a high score for this board (if not, congrats, you have the high score!). If there is, it checks if the current &lt;code&gt;turn_count&lt;/code&gt; is lower than the current high score (remember, lower is better in bingo) and if it is, updates the board's high score accordingly. Let's build another method to handle updating the user's scores too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def update_scores(turns_to_score, high_score)
    self[turns_to_score] = turn_count
    self.save
    update_high_score(high_score)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can fill out the rest of &lt;code&gt;handle_match&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_match index
    update_filled_spaces(index)
    update_scores(:turns_to_full, :full_high_score) if is_full?
    update_scores(:turns_to_x, :x_high_score) if has_new_x?
    update_scores(:turns_to_line, :line_high_score) if has_new_line?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using conditionals to update the appropriate scores if the necessary conditions have been met. Let's see it all together now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def remove_from_unused num
    unused_nums_arr = self.unused_nums.split(' ')
    unused_nums_arr.delete num
    update(unused_nums: unused_nums_arr.join(' '))
end

def count_turn
    count = self.turn_count ? self.turn_count : 0
    update(turn_count: count + 1)
end

def get_match num
    layout_arr = self.board.layout.split(' ')
    layout_arr.find_index num
end

def update_filled_spaces index
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    filled_spaces_arr.push(index)
    update(filled_spaces: filled_spaces_arr.join(' '))
end

def is_full?
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    filled_spaces_arr.count == 25
end

def has_new_x?
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    !self.turns_to_x &amp;amp;&amp;amp; (Board::X_WIN - filled_spaces_arr).empty?
end

def has_new_line?
    filled_spaces_arr = self.filled_spaces ? self.filled_spaces.split(' ') : []
    !self.turns_to_line &amp;amp;&amp;amp; Board::LINE_WIN_COMBINATIONS.find { |combo| (combo - filled_spaces_arr).empty? }
end

def update_high_score high_score
    if !self.board[high_score] || turn_count &amp;lt; self.board[high_score]
        self.board[high_score] = turn_count
        self.board.save
    end
end

def update_scores(turns_to_score, high_score)
    self[turns_to_score] = turn_count
    self.save
    update_high_score(high_score)
end

def handle_match index
    update_filled_spaces(index)
    update_scores(:turns_to_full, :full_high_score) if is_full?
    update_scores(:turns_to_x, :x_high_score) if has_new_x?
    update_scores(:turns_to_line, :line_high_score) if has_new_line?
end

def play_turn num
     remove_from_unused(num)
     count_turn
     match = get_match(num)
     handle_match(match) if match
 end

def sim_play
    play_turn(unused_nums.split(' ').sample) until is_full?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beautiful! We've built a fully functioning bingo game! Let's look at the seed file to see how simple the code for seeding our database can now be (with some help from the &lt;a href="https://github.com/faker-ruby/faker"&gt;Faker&lt;/a&gt; gem):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;puts "Seeding..."

# generate 20 unique boards
Board.generate_board until Board.all.count == 20

#generate fake users and passwords
5.times do
    name = Faker::Name.name
    username = Faker::Beer.brand.gsub(/\s+/, "")
    password = Password.create(password: Faker::Types.rb_string)
    Player.create(name: name, username: username, password_id: password[:id])
end



#simulate each user playing each board (note: this will take a while. The puts are to help track progress)
Player.all.each do |player|
    puts "player #{player[:id]}"
    Board.all.each do |board|
        puts "board #{board[:id]}"
        unused_nums = (0..99).to_a.join(' ')
        new_game = PlayedBoard.create(player_id: player[:id], board_id: board[:id], unused_nums: unused_nums)
        new_game.sim_play
        puts new_game[:turn_count]
    end
end

puts "Done seeding!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This takes a while, but when it's done you'll have twenty unique boards, five users, and one hundred &lt;code&gt;played_boards&lt;/code&gt;! Please feel free to check out the &lt;a href="https://github.com/nkulik94/sinatra-react-bingo-frontend"&gt;repo&lt;/a&gt;, and tell me what you think!&lt;/p&gt;

&lt;p&gt;Questions? Feedback? Drop it in the comments, connect with me on &lt;a href="https://www.linkedin.com/in/naftali-kulik-se/"&gt;LinkedIn&lt;/a&gt;, or email me at &lt;a href="//mailto:naftalikulikse@gmail.com"&gt;naftalikulikse@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Book Wyrms 2.0: "React"ing to my First Project</title>
      <dc:creator>Naftali Kulik</dc:creator>
      <pubDate>Wed, 15 Jun 2022 17:55:12 +0000</pubDate>
      <link>https://dev.to/nkulik94/book-wyrms-20-reacting-to-my-first-project-1omf</link>
      <guid>https://dev.to/nkulik94/book-wyrms-20-reacting-to-my-first-project-1omf</guid>
      <description>&lt;p&gt;When I started working on my first big project, my goal was to hit it out of the park. I wanted to put all of my (admittedly limited) knowledge to use and build something I could be proud of. The result was 750 lines of vanilla JavaScript code that, while it worked beautifully, would be quite a challenging task to read for anyone other than me, who wrote it (and we'll see if even I can read it after I have a year or two to forget about it). Don't get me wrong, I am quite proud of the effort. However, even at the time, I was well aware that there was probably a better way to do it. My goal was to put the knowledge that I had to the test, and I did.&lt;/p&gt;

&lt;p&gt;Enter React. Little did I know at the time, my project was a tailor-made React application, only without React. Let's take a look at some of the code and see how React could (and in fact &lt;a href="https://github.com/nkulik94/book-wyrms-react" rel="noopener noreferrer"&gt;did&lt;/a&gt;) allow me to completely refactor the code to make a much more organized application, while perhaps even adding or improving functionality. For obvious reasons, I will not be going through all 750 lines of code here, this is a blog, not a book. It's &lt;a href="https://github.com/nkulik94/book-wyrmz" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you want to take a crack at it yourself.&lt;/p&gt;

&lt;p&gt;Let's quickly walk through the functionality of the app before we continue (or you can watch this &lt;a href="https://youtu.be/iTsHy6b8rUs" rel="noopener noreferrer"&gt;walkthrough video&lt;/a&gt;). The app is essentially a knockoff of &lt;a href="https://www.goodreads.com/" rel="noopener noreferrer"&gt;Goodreads&lt;/a&gt;. The user can search books by title or author (book information obtained via the Open Library &lt;a href="https://openlibrary.org/developers/api" rel="noopener noreferrer"&gt;API&lt;/a&gt;), and view detailed information about the book when a search result item is selected. Users can also log in or create an account, allowing them to rate and review books, as well as add books to a read list or wish list. Here's a screenshot of the app in action:&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%2F5hmvfw89ycs8hfvx28m4.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%2F5hmvfw89ycs8hfvx28m4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the picture, much of the app looks like it could be made up of React components. The first and perhaps biggest advantage of using React would be the ability to use &lt;a href="https://reactjs.org/docs/introducing-jsx.html" rel="noopener noreferrer"&gt;JSX&lt;/a&gt; so that something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ul = document.createElement('ul')
    ul.id = id
    document.getElementById(divId).appendChild(ul)
    books.map(book =&amp;gt; {
        let rating
        const cover = book.cover.substring(0, book.cover.length - 5) + 'S.jpg'
        book.ownRating === 'none' ? rating = 'You have not yet rated this book' : rating = `You have given this book a rating of ${book.ownRating} out of 5`
        const li = document.createElement('li')
        li.className = `li-for-${id}`
        const bookCover = document.createElement('img')
        bookCover.src = `${cover}`
        li.appendChild(bookCover)
        const h4 = document.createElement('h4')
        h4.textContent = `${book.title}`
        li.appendChild(h4)
        li.appendChild(document.createElement('br'))
        if (id === 'readList') {
            const bookRating = document.createElement('p')
            bookRating.textContent = `${rating}`
            li.appendChild(bookRating)
            let review
            book.review === 'none' ? review = '&amp;lt;p&amp;gt;You have not reviewed this book&amp;lt;/p&amp;gt;' : review = `&amp;lt;h5&amp;gt;Your Review:&amp;lt;/h5&amp;gt;&amp;lt;p&amp;gt;${book.review}&amp;lt;/p&amp;gt;&amp;lt;br&amp;gt;&amp;lt;button id="delete-review-${book.id}"&amp;gt;Delete this review&amp;lt;/button&amp;gt;`
            const bookReview = document.createElement('p')
            bookReview.innerHTML = review
            bookReview.className = 'user-review'
            li.appendChild(bookReview)
        }
        if (id === 'wishList') {
            const addToRead = document.createElement('button')
            addToRead.id = `make-read-book-${book.id}`
            addToRead.textContent = 'Add this book to your read list'
            li.appendChild(addToRead)
            addToRead.addEventListener('click', () =&amp;gt; {
                currentUser.wishList.splice(currentUser.wishList.indexOf(book), 1)
                currentUser.readList.push(book)
                updateBookFromUserEnd('wantToRead', book.id, currentUser.username, true)
                handlePostPatch('users', 'PATCH', currentUser, updateUserCallback)
            })
            const removeBook = document.createElement('button')
            removeBook.id = `remove-book-${book.id}`
            removeBook.textContent = 'Remove this book'
            removeBook.style.margin = '3px'
            li.appendChild(removeBook)
            removeBook.addEventListener('click', () =&amp;gt; {
                currentUser.wishList.splice(currentUser.wishList.indexOf(book), 1)
                updateBookFromUserEnd('wantToRead', book.id, currentUser.username, false)
                handlePostPatch('users', 'PATCH', currentUser, updateUserCallback)
            })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be drastically simplified by using JSX to simply write out the HTML syntax in your React component. This alone would've slashed the amount of code by half and made it significantly more readable.&lt;/p&gt;

&lt;p&gt;However, it still would have been a mostly disorganized jumble of different functions responsible for accomplishing different tasks. Dividing these into separate files, or components can go a long way toward organizing and simplifying the code. Let's take a look at some of the functions from the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;renderPageButton(pages, id, list)

renderSearchResultPages(i, id)

renderBookResults(book)

renderDetailedBook()

renderBasicUserInfo(user)

renderUserLists(books, id, divId)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmmm. Those look like they have much in common with React components! Each of those functions is responsible for rendering DOM nodes, and they even take arguments that are similar to props in that they allow the same function to be used for several parts of the same document by passing different information down to the function. One can easily imagine how this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bookList.map(book =&amp;gt; renderBookResult(book))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can get lost somewhere in a 750-line code jungle. A separate file (component) can make this easy to read and easy to find if necessary. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import BookCard from './BookCard'

function BookList({ books }) {
    return (
        &amp;lt;ul&amp;gt;
            {books.map(book =&amp;gt; &amp;lt;BookCard book={book} key={book.id} /&amp;gt;)}
        &amp;lt;/ul&amp;gt;
    )
}

export default BookList
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the &lt;code&gt;BookList&lt;/code&gt; component lives in its own file and can be imported wherever it's needed, with the appropriate list passed as props. The imported &lt;code&gt;BookCard&lt;/code&gt; component probably looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import SearchResultBtn from './SearchResultBtn';

function BookCard({ book }) {

    return (
        &amp;lt;li className='book-card'&amp;gt;
            &amp;lt;img src={book.cover} alt={book.title} /&amp;gt;
            &amp;lt;h5&amp;gt;{book.title}&amp;lt;/h5&amp;gt;
            &amp;lt;p&amp;gt;By {book.author}&amp;lt;/p&amp;gt;
            &amp;lt;SearchResultBtn /&amp;gt;
        &amp;lt;/li&amp;gt;
    )
}

export default BookCard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and is generic enough to be used for many different book cards.&lt;/p&gt;

&lt;p&gt;There's one more feature of React that seems like it was made for this app, and that is state. Take the following code, copied from the Book Wyrm code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let currentBook;

let currentUser;

function updateBook(book) {
    currentBook = book
    renderDetailedBook()
    return currentBook
}

function updateUser(user) {
    currentUser = user
    renderBasicUserInfo(currentUser)
    return currentUser
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run through what state does for a moment. State allows you to save information to a variable, and update that variable by passing the new value to a setter function. Additionally, the component will re-render every time the state variable is modified. Now take a look at the above code again. Isn't that what we're doing? The &lt;code&gt;currentBook&lt;/code&gt; and &lt;code&gt;currentUser&lt;/code&gt; variables are declared but not assigned, and the &lt;code&gt;updateBook&lt;/code&gt; and &lt;code&gt;updateUser&lt;/code&gt; functions assign whatever value is passed as an argument to the appropriate variable and re-render the appropriate DOM element to reflect the changes. Using state, we can write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';

const [currentBook, setBook] = useState({});

const [currentUser, setUser] = useState({});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to accomplish the same thing. These variables and setter functions can then be passed down to whichever components need them via props, or, as I did in &lt;a href="https://github.com/nkulik94/book-wyrms-react" rel="noopener noreferrer"&gt;my own refactor&lt;/a&gt;, used with &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;context&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In conclusion, one can easily see how not only was I able to completely refactor my code in a way that made it (mostly) more readable and organized, I was actually able to add functionality without sacrificing clarity, and even used &lt;code&gt;react-router-dom&lt;/code&gt; (a topic for a different time perhaps) to make it appear as if the application consisted of several pages and to seamlessly navigate between them. I have deployed both the &lt;a href="https://nkulik94.github.io/book-wyrmz/" rel="noopener noreferrer"&gt;first version&lt;/a&gt; and the &lt;a href="https://sweet-zuccutto-773929.netlify.app/" rel="noopener noreferrer"&gt;second version&lt;/a&gt;, which, if you compare the two shows that not only can React help you make your code more easily readable and organized, it (with a little help from React Bootstrap!) can also help drastically improve the functionality of your app, as well as the user experience.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Academic vs Intuitive Understanding Part II: Speaking the Language</title>
      <dc:creator>Naftali Kulik</dc:creator>
      <pubDate>Thu, 19 May 2022 21:00:59 +0000</pubDate>
      <link>https://dev.to/nkulik94/academic-vs-intuitive-understanding-part-ii-speaking-the-language-5647</link>
      <guid>https://dev.to/nkulik94/academic-vs-intuitive-understanding-part-ii-speaking-the-language-5647</guid>
      <description>&lt;p&gt;When I was a kid, I always pictured a computer programmer as someone sitting hunched over a black and white screen feverishly punching indecipherable combinations of letters and numbers into their keyboard, filling up line after line with what was essentially memorized gibberish. To my mind, the word "code" evoked images of a vast and immutable library of "codes", random character combinations intended to be entered into some part of a computer that I had never seen before to make my computer's programs do the stuff they were supposed to do. Let's just say that the idea of doing something like that for a living never really appealed to me much. The more I learn, the more I see how wrong I was about all that. Well, everything other than the part about sitting hunched over a screen all day. Code is flexible, versatile, and above all, it actually &lt;em&gt;makes sense&lt;/em&gt;. Asking a program if &lt;code&gt;1 + 1 === 2&lt;/code&gt; does exactly what you would expect it to do, and the built-in methods (specifically in JavaScript, I don't know anything else yet) have names that pretty much tell you exactly what they're doing. Want to find a specific element in an array? Well, chances are that even if you know nothing at all it won't take a genius to guess that the method called &lt;code&gt;.find()&lt;/code&gt; might be the one that you're looking for. And it's not just the names. Digging under the hood of built-in JavaScript methods shows that they follow an intuitive and logical (if sometimes complicated!) process to do what they do. The fact that it's called a programming "language" is no coincidence. Language is fluid and flexible, and one can use language to express anything, often in multiple ways. To be fluent in a language is not to have a memorized list of words in your head, rather it's about having an intuitive grasp of how it works, allowing you to manipulate the language to express yourself in the way that you want. One who is not fluent in a language cannot express themselves in that language nearly as well, even if they have memorized many individual words. Making the jump from knowledge to fluency is something that can only be done with practice, which was something that I explored in detail in &lt;a href="https://dev.to/nkulik94/academic-vs-intuitive-understanding-aka-practice-makes-competent-4kc0"&gt;my first post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am not claiming to be anywhere near "fluent" in JavaScript. I am still a relative beginner who is learning new things every day. However, I am starting to see growth. At the time that I wrote Part I, testing code was more about seeing what would go wrong than it was about seeing if it'd work. Working on my first major project for Flatiron School, I was pleasantly surprised that for the most part, my code did what I thought it would do the first time. I definitely ran into my fair share of bugs, but most of the time it was either something I overlooked or something written early on in the program coming back to bite me later on.&lt;/p&gt;

&lt;p&gt;As I've become more fluent, I find myself able to manipulate JavaScript in different, creative ways to accomplish my goals. For example, if you're dealing with multiple &lt;code&gt;fetch&lt;/code&gt; requests that all do different things, you can write out a bunch of different requests with the appropriate callbacks, or you can write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function handleGet(url, callback) {
    fetch(url)
    .then(res =&amp;gt; res.json())
    .then(data =&amp;gt; callback(data))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Config {
    constructor(method, body) {
        this.method = method,
        this.headers = {
            "Content-type": "application/json",
            "Accept": "application/json"
        },
        this.body = JSON.stringify(body)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function handlePostPatch(source, method, obj, callback) {
    let url
    method === 'POST' ? url = source : url = `${source}/${obj.id}`
    fetch(url, new Config(method, obj))
    .then(res =&amp;gt; res.json())
    .then(data =&amp;gt; callback(data))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all you have to do is build the appropriate callbacks and pass them as arguments in the above functions as needed. As a side point, in reference to what I wrote earlier about JavaScript methods generally having easy-to-understand names, sometimes that name sounds like it was the first thing that popped into the head of the person who developed it. I bring this up now because seriously, stringify?? It's still pretty self-explanatory though, so who cares? I definitely don't.&lt;/p&gt;

&lt;p&gt;I'd like to share another neat trick that, while it probably wouldn't usually be necessary, demonstrates how disparate techniques can be combined to do what needs to be done in creative ways. Let's outline a hypothetical case. Say you have an app that renders data obtained from different sources, for example, information about &lt;a href="https://youtu.be/iTsHy6b8rUs"&gt;books&lt;/a&gt;. Many or all of them were assigned a specific &lt;code&gt;className&lt;/code&gt; when they were rendered to the DOM, and now you want to iterate over the &lt;code&gt;HTMLCollection&lt;/code&gt; for that &lt;code&gt;className&lt;/code&gt; to add some sort of event listener that would send data via a &lt;code&gt;PATCH&lt;/code&gt; request, perhaps the contents of a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;, and update the server accordingly. The problem you may be running into now is that to send a &lt;code&gt;PATCH&lt;/code&gt; you need the id of whatever it is that you are updating. That may have come back as part of the request that originally was made to render the information, but how can you store that somewhere where it can be easily accessed and associated with the correct element? Generally, you'd add the event listener whenever the element was rendered to the DOM, while you're still working with the server's response and have access to the id. For argument's sake, let's say that isn't possible or practical for some reason or the other. How and where can you store the id in a way that it'd be associated with the correct element when the event listener is fired? One way to do this would be to create an &lt;code&gt;object&lt;/code&gt; that contains the element and id in the callback that handles the original response and to push the object into an &lt;code&gt;array&lt;/code&gt;. Then your event listener callback can iterate over the &lt;code&gt;array&lt;/code&gt; to find the id that's matched with the correct element and use it for the &lt;code&gt;PATCH&lt;/code&gt;. However, this involves a lot of iteration, so maybe instead of iterating over the &lt;code&gt;HTMLCollection&lt;/code&gt; for the relevant &lt;code&gt;className&lt;/code&gt;, maybe you can iterate over the &lt;code&gt;array&lt;/code&gt; of &lt;code&gt;objects&lt;/code&gt; itself to add the event listener and have the id right there. Then you'd end up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bookArr.map(bookObj =&amp;gt; {
    bookObj.book.addEventListener('submit', () =&amp;gt; {
        callback(bookObj.id)
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there's a way to do this without creating a whole new array, by creatively manipulating &lt;code&gt;strings&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick disclaimer, many of these string methods use iteration under the hood, so there's a good chance this isn't any more efficient than the methods I just presented, and perhaps even less so. I just think it's a cool demonstration of the diverse things you can do with different methods. I still haven't fully wrapped my brain around how Big O notation works, so take anything I say about efficiency with a grain of salt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While handling the original request and rendering it to the DOM, add an id to the element that you are planning to add an event listener to that looks something like this (assuming &lt;code&gt;data&lt;/code&gt; is the &lt;code&gt;object&lt;/code&gt; from the server response that you are currently handling):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;submitForm.id = `form-for-${data.id}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in the event listener callback just to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const idSplit = event.target.id.split('-')
const id = idSplit.slice(idSplit.length - 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's your id! Ok fine, it's not really any more efficient than the previous methods, but it's still cool.&lt;/p&gt;

&lt;p&gt;The more you practice, the more you become "fluent" in JavaScript. The more fluency you have, the more versatile and flexible your code can become. Eventually, perhaps writing code can become as natural as talking or writing in your native language, and creating functional applications will just become a matter of "telling" JavaScript what you want to be done, in a smooth and efficient manner.&lt;/p&gt;

&lt;p&gt;Edit 5/27/22: There's a lot I still have to learn, such as the &lt;code&gt;name&lt;/code&gt; attribute which would probably render my little trick with the &lt;code&gt;id&lt;/code&gt; completely pointless. I believe that the point I was trying to make is still valid though.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Academic vs Intuitive understanding (aka practice makes competent)</title>
      <dc:creator>Naftali Kulik</dc:creator>
      <pubDate>Sun, 08 May 2022 16:37:46 +0000</pubDate>
      <link>https://dev.to/nkulik94/academic-vs-intuitive-understanding-aka-practice-makes-competent-4kc0</link>
      <guid>https://dev.to/nkulik94/academic-vs-intuitive-understanding-aka-practice-makes-competent-4kc0</guid>
      <description>&lt;p&gt;Welcome to my first blog post!&lt;/p&gt;

&lt;p&gt;I am just starting out on my journey as a student at Flatiron School, and I'd like to share a few insights that I've picked up so far along the way. Specifically, I'd like to discuss how much there is to gain from practicing your code and seeing how it works over just learning the rules, syntax, etc.&lt;/p&gt;

&lt;p&gt;One thing that jumps out at me, again and again, is the vast gap between having &lt;em&gt;knowledge&lt;/em&gt; (i.e. academic understanding) of something and actually &lt;em&gt;getting&lt;/em&gt; (intuitive understanding) something in a way that the knowledge can be applied properly and practically. This in fact appears to be a major difference between the way Flatiron School teaches and the way many college courses are taught. Your average college course may teach you all there is to know about programming; Flatiron School &lt;em&gt;makes you into a programmer&lt;/em&gt;. The difference is subtle but profound.&lt;/p&gt;

&lt;p&gt;I'll give a quick example of this to demonstrate what I mean. It's hard for me to imagine now, but when I completed my prework for Flatiron I had no idea how iteration/looping could be useful. That's not to say that I didn't understand the basics of how it worked, but I hadn't intuitively grasped how it could actually be applied in a meaningful fashion. Because of this, when I was creating a website for my prework project, it never occurred to me that this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flipCards(lineOne, 0, 0);
flipCards(lineOne, 1, 1);
flipCards(lineOne, 2, 2);
flipCards(lineOne, 3, 3);
flipCards(lineOne, 4, 4);
flipCards(lineOne, 5, 5);
flipCards(lineTwo, 0, 6);
flipCards(lineTwo, 1, 7);
flipCards(lineTwo, 2, 8);
flipCards(lineTwo, 3, 9);
flipCards(lineTwo, 4, 10);
flipCards(lineTwo, 5, 11);
flipCards(lineThree, 0, 12);
flipCards(lineThree, 1, 13);
flipCards(lineThree, 2, 14);
flipCards(lineThree, 3, 15);
flipCards(lineThree, 4, 16);
flipCards(lineThree, 5, 17);
flipCards(lineFour, 0, 18);
flipCards(lineFour, 1, 19);
flipCards(lineFour, 2, 20);
flipCards(lineFour, 3, 21);
flipCards(lineFour, 4, 22);
flipCards(lineFour, 5, 23);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with only a few minor modifications to my code could have looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (let i = 0; i &amp;lt; allCards.length; i++) {
    flipCards(i)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I rarely write code without using some form of iteration or looping but at the time it wasn't so simple.&lt;/p&gt;

&lt;p&gt;So how do you make the jump? How do you go from academic knowledge to intuitive understanding? I've found the answer to be practice, or more specifically &lt;em&gt;making mistakes&lt;/em&gt;. "Learning from your mistakes" is a cliché that may be older than computer programming itself, but rarely can it be applied quite as literally as it can when it comes to coding. By working through your code and figuring out what it's actually doing vs what you think it should be doing you can gain more than you ever would by "book" learning alone. Allow me to take you through some code that's based on code that I wrote, and demonstrate how at every step every mistake I made led me to a deeper and more complete understanding of the code I was working with.&lt;/p&gt;

&lt;p&gt;Say we have an &lt;code&gt;object&lt;/code&gt; with car manufacturers as its keys, some with empty &lt;code&gt;strings&lt;/code&gt; as values, some with an &lt;code&gt;array&lt;/code&gt; containing some of the models of car that are produced by that company:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const cars = {
    honda: '',
    toyota: ['corolla', 'camry', 'avalon', 'sienna'],
    gmc: '',
    chrysler: '',
    ford: ['explorer', 'fusion'],
    hyundai: ['elantra', 'sonata', 'genesis', 'santa fe'],
    infiniti: ''
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's say I'd like to render these cars as a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; on my webpage, with a nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; to list the models of car that are included for those manufactures that have them. If we were just making a list of manufacturers (the keys) that would be fairly simple. We have a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; in our &lt;code&gt;html&lt;/code&gt; file with an &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;#main-list&lt;/code&gt;. Let's build a function that would create a &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; tag and add it to this &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeLi(car) {
    const li = document.createElement('li')
    li.textContent = car
    document.getElementById('main-list').appendChild(li)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use a simple &lt;code&gt;for...in&lt;/code&gt; to create the list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (const car in cars) {
    makeLi(car)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's see what we get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9kZbtiup--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wqgtxn7yc5umvb9wyl2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9kZbtiup--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wqgtxn7yc5umvb9wyl2b.png" alt="Image description" width="735" height="193"&gt;&lt;/a&gt;&lt;br&gt;
That was easy!&lt;/p&gt;

&lt;p&gt;However, we'd like to add the nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; so let's see how we can do that.&lt;/p&gt;

&lt;p&gt;First let's add another parameter to &lt;code&gt;makeLi&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeLi(car, id) {
    const li = document.createElement('li')
    li.textContent = car
    document.getElementById(id).appendChild(li)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is the same, except that the &lt;code&gt;id&lt;/code&gt; of the &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; is passed as an argument instead of being spelled out in the function.&lt;/p&gt;

&lt;p&gt;Now we'll start building another function. This one will start off the same as &lt;code&gt;makeLi&lt;/code&gt; but will have a few extra steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeLiWithNestedUl(car) {
    const li = document.createElement('li')
    li.textContent = car
    document.getElementById('main-list').appendChild(li)
    const ul = document.createElement('ul')
    ul.id = 'child-ul'
    li.appendChild(ul)
    cars.car.map(model =&amp;gt; makeLi(model, 'child-ul'))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's update our &lt;code&gt;for..in&lt;/code&gt; with a simple ternary statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (const car in cars) {
    cars.car === '' ? makeLi(car, 'main-list') : makeLiWithNestedUl(car)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let's see what we get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T3Pdu5DT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bf2yn0lwxk4myysz6t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T3Pdu5DT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bf2yn0lwxk4myysz6t9.png" alt="Image description" width="880" height="148"&gt;&lt;/a&gt;&lt;br&gt;
Well... Seems like we just ran into our first learning opportunity! The error message is telling us that JavaScript apparently doesn't recognize our &lt;code&gt;.map()&lt;/code&gt; method for what it is, rather it seems to be trying to give the word "map" some sort of value (which doesn't exist). It must be that &lt;code&gt;cars.car&lt;/code&gt;, which should return the value of whichever key our &lt;code&gt;for..in&lt;/code&gt; loop is passing as an argument to the function, is not being recognized as an &lt;code&gt;array&lt;/code&gt; for some reason. Let's use &lt;code&gt;console.log()&lt;/code&gt; to do some troubleshooting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (const car in cars) {
    console.log(cars.car)
    //cars.car === '' ? makeLi(car, 'main-list') : makeLiWithNestedUl(car)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at our console to see what we've gotten:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DnFw16N1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/prrskofrjuc8t3bkpry5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DnFw16N1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/prrskofrjuc8t3bkpry5.png" alt="Image description" width="744" height="183"&gt;&lt;/a&gt;&lt;br&gt;
That's weird... It seems that &lt;code&gt;cars.car&lt;/code&gt; is returning &lt;code&gt;undefined&lt;/code&gt;. Have we misunderstood something about our &lt;code&gt;for..in&lt;/code&gt; loop? We'll quickly make sure we haven't missed something here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (const car in cars) {
    console.log(car)
    //cars.car === '' ? makeLi(car, 'main-list') : makeLiWithNestedUl(car)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check the console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ukMTnzAZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grrbb25g8hse5tti6ps6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ukMTnzAZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grrbb25g8hse5tti6ps6.png" alt="Image description" width="752" height="297"&gt;&lt;/a&gt;&lt;br&gt;
It seems that &lt;code&gt;car&lt;/code&gt; does in fact return the keys to our &lt;code&gt;cars&lt;/code&gt; object, so why is &lt;code&gt;cars.car&lt;/code&gt; undefined? We've just learned our first lesson! Now I've realized the implications of something I already knew but perhaps never internalized the way I needed to. All keys are really &lt;code&gt;strings&lt;/code&gt;. Our &lt;code&gt;for..in&lt;/code&gt; is saving the keys of &lt;code&gt;cars&lt;/code&gt; to the &lt;code&gt;car&lt;/code&gt; variable &lt;em&gt;as strings&lt;/em&gt;, and therefore our dot notation isn't working! In fact, if we look at our DOM, it seems the ternary expression didn't work properly either:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nQFpkDt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7219erhua3ysld99ch8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nQFpkDt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7219erhua3ysld99ch8.png" alt="Image description" width="751" height="174"&gt;&lt;/a&gt;&lt;br&gt;
It seems that our &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; for honda has a nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; despite its value in our &lt;code&gt;cars&lt;/code&gt; object being an empty &lt;code&gt;string&lt;/code&gt;. Our ternary statement was checking if &lt;code&gt;cars.car === ''&lt;/code&gt; and &lt;em&gt;was returning false&lt;/em&gt;, because &lt;code&gt;cars.car&lt;/code&gt; was in fact &lt;code&gt;undefined&lt;/code&gt;! Our code therefore called the &lt;code&gt;makeLiWithNestedUl&lt;/code&gt; function on the first key of our &lt;code&gt;cars&lt;/code&gt; object, honda, and then ran into an error when we tried using the &lt;code&gt;.map()&lt;/code&gt; method on &lt;code&gt;cars.car&lt;/code&gt;, which was &lt;code&gt;undefined&lt;/code&gt;. Let's do a quick &lt;code&gt;console.log()&lt;/code&gt;, this time with bracket notation, to confirm our suspicions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (const car in cars) {
    console.log(cars[car])
    //cars.car === '' ? makeLi(car, 'main-list') : makeLiWithNestedUl(car)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6WhnXEEK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0wjst6es84qvqa7eix2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6WhnXEEK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0wjst6es84qvqa7eix2.png" alt="Image description" width="752" height="562"&gt;&lt;/a&gt;&lt;br&gt;
Perfect! It's logging the correct values for all of our keys! (In some cases that's nothing, i.e. an empty &lt;code&gt;string&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Let's get rid of the &lt;code&gt;console.log()&lt;/code&gt;, uncomment our ternary statement, change our dot notation to bracket notation (both in the ternary and in the &lt;code&gt;makeLiWithNestedUl&lt;/code&gt; function), and see what happens!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OfjLCrbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngeq032m5xb6y243niln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OfjLCrbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngeq032m5xb6y243niln.png" alt="Image description" width="478" height="440"&gt;&lt;/a&gt;&lt;br&gt;
Oy vey. Our bracket notation seems to have fixed our ternary statement and gotten our &lt;code&gt;.map()&lt;/code&gt; method to work. However, for some reason, all of the nested &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements are being added to the first nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, under toyota. Let's take a look at our DOM to see if ford and hyundai aren't getting their &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;s for some reason.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ztQzQ6CU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahmqu4xv4tb9y3c6ok6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ztQzQ6CU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahmqu4xv4tb9y3c6ok6a.png" alt="Image description" width="755" height="511"&gt;&lt;/a&gt;&lt;br&gt;
Hmmm. They definitely are getting nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;s added, but I think our mistake is fairly obvious now. We've accidentally assigned the same &lt;code&gt;id&lt;/code&gt; to all of our nested &lt;code&gt;ul&lt;/code&gt;s. There are two lessons to be learned here. First of all, although an &lt;code&gt;html&lt;/code&gt; document isn't supposed to have more than one element with the same id, JavaScript apparently has no problem adding the same &lt;code&gt;id&lt;/code&gt; to more than one DOM node if we tell it to. Secondly, if more than one DOM node or element has the same &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;document.getElementByID()&lt;/code&gt; will return the first element with that &lt;code&gt;id&lt;/code&gt;. Let's look at our functions again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeLi(car, id) {
    const li = document.createElement('li')
    li.textContent = car
    document.getElementById(id).appendChild(li)
}
function makeLiWithNestedUl(car) {
    const li = document.createElement('li')
    li.textContent = car
    document.getElementById('main-list').appendChild(li)
    const ul = document.createElement('ul')
    ul.id = 'child-ul'
    li.appendChild(ul)
    cars[car].map(model =&amp;gt; makeLi(model, 'child-ul'))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;makeLiWithNestedUl&lt;/code&gt; is calling &lt;code&gt;makeLi&lt;/code&gt; and passing &lt;code&gt;'child-ul'&lt;/code&gt; as the argument for the &lt;code&gt;id&lt;/code&gt; parameter. Because of this, all of our nested &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;s are being added to the first &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; with an &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;'child-ul'&lt;/code&gt;, which is the one for toyota.&lt;/p&gt;

&lt;p&gt;How can we assign different &lt;code&gt;id&lt;/code&gt;s to our nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;s while still effectively using iteration? Here's where we can use a simple tool that's way more powerful than I realized when I first learned about it. Some simple string interpolation should allow us to assign unique &lt;code&gt;id&lt;/code&gt;s to each nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ul.id = `${car}-list`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cars[car].map(model =&amp;gt; makeLi(model, `${car}-list`))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's our updated function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeLiWithNestedUl(car) {
    const li = document.createElement('li')
    li.textContent = car
    document.getElementById('main-list').appendChild(li)
    const ul = document.createElement('ul')
    ul.id = `${car}-list`
    li.appendChild(ul)
    cars[car].map(model =&amp;gt; makeLi(model, `${car}-list`))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's refresh our browser and see the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t0eyExZ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/an2seyhot12xld6mdr01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t0eyExZ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/an2seyhot12xld6mdr01.png" alt="Image description" width="880" height="368"&gt;&lt;/a&gt;&lt;br&gt;
We did it!&lt;/p&gt;

&lt;p&gt;Let's go a bit further. There's more code to write, more mistakes to be made, and more lessons to learn!&lt;/p&gt;

&lt;p&gt;I'd like to be able to change the color of each car manufacturer name to blue when it's clicked on, and each car model name to red when its clicked on. I'd also like for both to be changed back to black when clicked again. Should be simple, right? We can create a relatively simple event listener. First let's modify our original functions a bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeLi(car, id, className) {
    const li = document.createElement('li')
    li.textContent = car
    li.className = className
    document.getElementById(id).appendChild(li)
}
function makeLiWithNestedUl(car) {
    const li = document.createElement('li')
    li.textContent = car
    li.className = 'parent-li'
    document.getElementById('main-list').appendChild(li)
    const ul = document.createElement('ul')
    ul.id = `${car}-list`
    li.appendChild(ul)
    cars[car].map(model =&amp;gt; makeLi(model, `${car}-list`, 'child-li'))
}
for (const car in cars) {
    cars[car] === '' ? makeLi(car, 'main-list', 'parent-li') : makeLiWithNestedUl(car)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I did here was add a parameter to my &lt;code&gt;makeLi&lt;/code&gt; function allowing me to assign a &lt;code&gt;className&lt;/code&gt; to the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element being created. This allows me to to assign separate &lt;code&gt;classNames&lt;/code&gt; for the parent and child &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements. Lets make some &lt;code&gt;arrays&lt;/code&gt; now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const parentLiArray = Array.from(document.getElementsByClassName('parent-li'))
const childArray = Array.from(document.getElementsByClassName('child-li'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's add some event listeners:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parentLiArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        li.style.color === 'blue' ? li.style.color = 'black' : li.style.color = 'blue'
    })
})

childArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        li.style.color === 'red' ? li.style.color = 'black' : li.style.color = 'red'
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! now let's check the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uMVMGeE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6keqkdgva31aaumxny6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uMVMGeE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6keqkdgva31aaumxny6.png" alt="Image description" width="476" height="408"&gt;&lt;/a&gt;&lt;br&gt;
Oops. We forgot that styles applied to a parent will also apply to the child unless otherwise specified. When we click on hyundai it's also turning its child elements blue. Let's give a default style to all of our &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; elements to prevent this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Array.from(document.getElementsByTagName('ul')).map(ul =&amp;gt; ul.style.color = 'black')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jm2uzPMz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxuanqfe6q1t3ho5pvrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jm2uzPMz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxuanqfe6q1t3ho5pvrw.png" alt="Image description" width="277" height="409"&gt;&lt;/a&gt;&lt;br&gt;
There we go! Uh-oh. We seem to be running into other issues though.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0DU9aHxA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/inch3lpoxfnhmvu7olaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0DU9aHxA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/inch3lpoxfnhmvu7olaf.png" alt="Image description" width="456" height="442"&gt;&lt;/a&gt;&lt;br&gt;
Why are our nested &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;s also turning blue? To make matters worse, they're not changing back to black when they are clicked again. Let's get some &lt;code&gt;console.log()&lt;/code&gt;s going again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parentLiArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        li.style.color === 'blue' ? li.style.color = 'black' : li.style.color = 'blue'
        console.log(e.target.style.color)
    })
})

childArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        li.style.color === 'red' ? li.style.color = 'black' : li.style.color = 'red'
        console.log(e.target.style.color)
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can check the console for some clues as to what's going on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FxqBpnfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etfk329s0mej3f8hzzab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FxqBpnfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etfk329s0mej3f8hzzab.png" alt="Image description" width="880" height="341"&gt;&lt;/a&gt;&lt;br&gt;
Now that's interesting. There are &lt;em&gt;two&lt;/em&gt; values being logged when the nested &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; is being clicked. The first is red, as it should be. The second is blue. Apparently our code is changing the color to red as it should, but then immediately changing it to blue. Clicking it again logs the same result. (You can take my word for it). Let's try a different &lt;code&gt;console.log()&lt;/code&gt; to see if our event listeners are behaving the way they should:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parentLiArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        li.style.color === 'blue' ? li.style.color = 'black' : li.style.color = 'blue'
        console.log(e.target)
    })
})

childArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        li.style.color === 'red' ? li.style.color = 'black' : li.style.color = 'red'
        console.log(e.target)
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check out the console again:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MrkyheR9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kvxu9y6hp9mvzcryfmm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MrkyheR9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kvxu9y6hp9mvzcryfmm6.png" alt="Image description" width="880" height="291"&gt;&lt;/a&gt;&lt;br&gt;
Fascinating. The clicked element is being logged twice! Making this mistake originally taught me something I actually hadn't known. Adding an event listener to a parent element will automatically add the same event listener to its children. When I clicked the child &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element, it first fired its own event listener, which checked if its style was set to red (it wasn't) and then changed it to red. That part worked perfectly. The problem was that after that the event listener for the parent fired, checked if the style was blue (it wasn't), and changed it to blue. The reason it didn't change back when clicked again was that it kept repeating the same process, checking if it was red, changing it to red, then checking if it was blue and changing it to blue. Now that we realize this maybe we only need one event listener for both! How can we do that? Let's see... We need some way for JavaScript to differentiate between the parent and child elements and act accordingly. I'm going to get rid of the event listener for the child &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements because we don't need it anymore. Now let's change up our other event listener a bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parentLiArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        if (li.className === 'parent-li') {
            li.style.color === 'blue' ? li.style.color = 'black' : li.style.color ='blue'
        } else {
            li.style.color === 'red' ? li.style.color = 'black' : li.style.color = 'red'
        }
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our event listener is first checking the &lt;code&gt;className&lt;/code&gt; of its target and acting accordingly, changing between blue and black if its &lt;code&gt;className&lt;/code&gt; is &lt;code&gt;'parent-li'&lt;/code&gt;, and changing between red and black if not. Let's try it in our browser again:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gtfTzmy2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxu4j9dk63el69jurbeg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gtfTzmy2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxu4j9dk63el69jurbeg.png" alt="Image description" width="476" height="407"&gt;&lt;/a&gt;&lt;br&gt;
Great! Now let's click a few of them again to make sure they change back to black:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wpl82v6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bo6mw0i974r5zmaneegx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wpl82v6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bo6mw0i974r5zmaneegx.png" alt="Image description" width="470" height="406"&gt;&lt;/a&gt;&lt;br&gt;
Perfect! We did it! Here's the completed, functioning code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const cars = {
    honda: '',
    toyota: ['corolla', 'camry', 'avalon', 'sienna'],
    gmc: '',
    chrysler: '',
    ford: ['explorer', 'fusion'],
    hyundai: ['elantra', 'sonata', 'genesis', 'santa fe'],
    infiniti: ''
};

function makeLi(car, id, className) {
    const li = document.createElement('li')
    li.textContent = car
    li.className = className
    document.getElementById(id).appendChild(li)
}
function makeLiWithNestedUl(car) {
    const li = document.createElement('li')
    li.textContent = car
    li.className = 'parent-li'
    document.getElementById('main-list').appendChild(li)
    const ul = document.createElement('ul')
    ul.id = `${car}-list`
    li.appendChild(ul)
    cars[car].map(model =&amp;gt; makeLi(model, `${car}-list`, 'child-li'))
}
for (const car in cars) {
    cars[car] === '' ? makeLi(car, 'main-list', 'parent-li') : makeLiWithNestedUl(car)
}

Array.from(document.getElementsByTagName('ul')).map(ul =&amp;gt; ul.style.color = 'black')

const parentLiArray = Array.from(document.getElementsByClassName('parent-li'))

parentLiArray.map(li =&amp;gt; {
    li.addEventListener('click', e =&amp;gt; {
        const li = e.target
        if (li.className === 'parent-li') {
            li.style.color === 'blue' ? li.style.color = 'black' : li.style.color ='blue'
        } else {
            li.style.color === 'red' ? li.style.color = 'black' : li.style.color = 'red'
        }
    })
})

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

&lt;/div&gt;



&lt;p&gt;I've now demonstrated just one small example of how practicing code, messing up, and figuring out what went wrong is the best and perhaps only way to truly understand and internalize how your code is &lt;em&gt;really&lt;/em&gt; working. The mistakes I made in this example are based on real mistakes I made and the steps I took to fix them. (It was quite frustrating at the time, let me tell you!) I am just starting out on my journey as a programmer and I am looking forward to many future mistakes! Thanks for hanging in there with me until the end of my first ever blog. Any and all feedback is welcome!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
