<?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: Wizard Health</title>
    <description>The latest articles on DEV Community by Wizard Health (@wizardhealth).</description>
    <link>https://dev.to/wizardhealth</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%2Forganization%2Fprofile_image%2F1493%2F1b14869b-97b2-448f-851e-c61595132119.png</url>
      <title>DEV Community: Wizard Health</title>
      <link>https://dev.to/wizardhealth</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wizardhealth"/>
    <language>en</language>
    <item>
      <title>Metaprogramming, ancestors chain and super.</title>
      <dc:creator>Dino</dc:creator>
      <pubDate>Mon, 13 Mar 2023 08:07:09 +0000</pubDate>
      <link>https://dev.to/wizardhealth/metaprogramming-ancestors-chain-and-super-2pbd</link>
      <guid>https://dev.to/wizardhealth/metaprogramming-ancestors-chain-and-super-2pbd</guid>
      <description>&lt;p&gt;Let's imagine we are building DSL similar to ActiveRecord associations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="n"&gt;associated_with&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;account&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Account associated with a Person"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to build this feature, we will create a new module that dynamically defines association methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Associations&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;associated_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"associated &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Associations&lt;/span&gt;

  &lt;span class="n"&gt;associated_with&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;account&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; "associated account"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;define_method&lt;/code&gt; creates an instance method on a receiver, which is exactly what we need.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;define_method&lt;/code&gt; basically has done this;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;account&lt;/span&gt;
    &lt;span class="s2"&gt;"associated account"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can easily validate this theory by inspecting the ancestors chain and instance methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; Person,Object,Kernel,BasicObject&lt;/span&gt;
&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [account]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Overwriting dynamically defined method
&lt;/h2&gt;

&lt;p&gt;If we wish to overwrite a dynamically defined method we can do it without any problems since this is just a "regular" instance method (albeit defined with some metaprogramming)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Associations&lt;/span&gt;

  &lt;span class="n"&gt;associated_with&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;account&lt;/span&gt;
    &lt;span class="s2"&gt;"overridden"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;account&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; "overridden"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, calling a &lt;strong&gt;super&lt;/strong&gt; when overriding will fail&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;account&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="s2"&gt;"overridden"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;account&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; `account': super: no superclass method `account' for ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes sense since we are calling &lt;code&gt;super&lt;/code&gt; on the method we've completely overwritten.&lt;/p&gt;

&lt;p&gt;In order for &lt;code&gt;super&lt;/code&gt; to work the method need to be defined in &lt;code&gt;Persons&lt;/code&gt; ancestors chain.&lt;/p&gt;

&lt;p&gt;We can do this by generating a new module on the fly, including that module in the class and define dynamic methods on that module instead of the class itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Associations&lt;/span&gt;
  &lt;span class="c1"&gt;# Create new module on the fly.&lt;/span&gt;
  &lt;span class="c1"&gt;# Include that module in the ancestor chain&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generated_association_methods&lt;/span&gt;
    &lt;span class="vi"&gt;@generated_association_methods&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="k"&gt;begin&lt;/span&gt;
                                         &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;const_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:GeneratedAssociationMethods&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                         &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;
                                         &lt;span class="n"&gt;mod&lt;/span&gt;
                                       &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;associated_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mixin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generated_association_methods&lt;/span&gt;

    &lt;span class="c1"&gt;# define methods on the newly created module&lt;/span&gt;
    &lt;span class="n"&gt;mixin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"associated &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Associations&lt;/span&gt;

  &lt;span class="n"&gt;associated_with&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now dynamically defined methods live inside the &lt;code&gt;Person::GeneratedAssociationMethods&lt;/code&gt;, which is part of ancestors chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; Person,**Person::GeneratedAssociationMethods**, Object,Kernel,BasicObject&lt;/span&gt;
&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; []&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So calling super will work fine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;account&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="s2"&gt;"overridden"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;account&lt;/span&gt;
  &lt;span class="c1"&gt;#=&amp;gt; "associated_account"&lt;/span&gt;
  &lt;span class="c1"&gt;#=&amp;gt; "overridden"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've seen this pattern used in Rails codebase in multiple places where this kind of behaviour is needed.&lt;/p&gt;

&lt;p&gt;✌️&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>ActiveRecord associations, scoped</title>
      <dc:creator>Dino</dc:creator>
      <pubDate>Fri, 17 Feb 2023 05:39:19 +0000</pubDate>
      <link>https://dev.to/wizardhealth/activerecord-associations-with-a-conditions-38ne</link>
      <guid>https://dev.to/wizardhealth/activerecord-associations-with-a-conditions-38ne</guid>
      <description>&lt;p&gt;ActiveRecord as a neat trick/ability which a lot of folks are not aware of.&lt;/p&gt;

&lt;p&gt;You can pass a block to association, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
 &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;admin: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What makes this even more interesting is that you can have multiple associations to the same model with different name and conditions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
 &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;
 &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:admin_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;admin: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;class_name: &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;@account.users&lt;/code&gt; will return collection of all users, but calling &lt;code&gt;@account.admin_users&lt;/code&gt; will return collection of only admin users.&lt;/p&gt;

&lt;p&gt;To make things even more interesting, when creating a new record through the association will comply with the association condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vi"&gt;@account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin_users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Admin User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;creates a new user with &lt;code&gt;admin&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since, condition executes in the context of the association object, you can also use scopes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:admin_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;admins&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;class_name: &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
 &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt;

 &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:admins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;admin: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="vi"&gt;@account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin_users&lt;/span&gt; &lt;span class="c1"&gt;# Works the same as examples above&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This associations will also work for eager loading also, calling&lt;br&gt;
&lt;code&gt;Account.includes(:admin_users)&lt;/code&gt; will eager load admin users.&lt;/p&gt;

&lt;p&gt;ActiveRecord can accomplish this because associations are built from &lt;code&gt;Relation&lt;/code&gt; objects, and you can use &lt;code&gt;Relation&lt;/code&gt; syntax to customize them.&lt;/p&gt;

&lt;p&gt;Isn't this neat!&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Install Ruby 3.2.0 with YJIT</title>
      <dc:creator>Sinan Mujan</dc:creator>
      <pubDate>Mon, 09 Jan 2023 13:08:40 +0000</pubDate>
      <link>https://dev.to/wizardhealth/install-ruby-320-with-yjit-3mmo</link>
      <guid>https://dev.to/wizardhealth/install-ruby-320-with-yjit-3mmo</guid>
      <description>&lt;p&gt;Ruby 3.2.0 is here and it offers &lt;a href="https://www.ruby-lang.org/en/news/2022/12/25/ruby-3-2-0-released/"&gt;some nice additions&lt;/a&gt; to the language.&lt;br&gt;
One of the most exciting new things is the addition of a compiler, YJIT. &lt;a href="https://github.com/Shopify/yjit"&gt;YJIT&lt;/a&gt; was created by the folks from Shopify and has been producion tested for a while, so it is safe to use in your environment.&lt;br&gt;
Some benchmarks show the difference in speed compared to Ruby without YJIT. I'll put some links if you want to know more:&lt;br&gt;
&lt;a href="https://speed.yjit.org/"&gt;https://speed.yjit.org/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.solnic.dev/p/benchmarking-ruby-32-with-yjit"&gt;https://www.solnic.dev/p/benchmarking-ruby-32-with-yjit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will show you the steps necessary to install Ruby using rbenv as it is the most popular Ruby version manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Rust
&lt;/h2&gt;

&lt;p&gt;To install Ruby 3.2.0 with YJIT, the first step is to install Rust. Rust is necessary if we want to add YJIT to our Ruby installation.&lt;br&gt;
The easiest way to install Rust is using Rustup, which is also the recommended way:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You'll be asked which type of installation you want, you can use the default.&lt;br&gt;
If you want alternative installation methods you can follow &lt;a href="https://forge.rust-lang.org/infra/other-installation-methods.html"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After that, update your $PATH variable. You can do this in many ways, I will show you how to do it by updating your bashrc or zshrc (depending which shell you use).&lt;/p&gt;

&lt;p&gt;Just open ~/.bashrc or ~/.zshrc using your preferred editor and at the end of the file just add the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export PATH="$HOME/.cargo/bin:$PATH"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will add the rust bin folder to your path, so you can check if rust was installed correctly easier. After that you have to source your file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source ~/.bashrc&lt;br&gt;
or&lt;br&gt;
source ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then you can check if the Rust installation was successful:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rustc --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should get an output like this that shows the version of Rust:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rustc 1.66.0 (69f9c33d7 2022-12-12).&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrade Ruby build
&lt;/h2&gt;

&lt;p&gt;Before you install Ruby 3.2.0 using rbenv, first you should update your ruby-build tool.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew update &amp;amp;&amp;amp; brew upgrade ruby-build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command could take some time, just so you know. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Ruby
&lt;/h2&gt;

&lt;p&gt;You are now ready to install Ruby 3.2.0 with YJIT.&lt;br&gt;
Enter the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUBY_CONFIGURE_OPTS="--enable-yjit" rbenv install 3.2.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You notice the RUBY_CONFIGURE_OPTS variable where you explicitly say that you want to enable YJIT. You can also add the --with-jemalloc flag as well to install jemalloc, the general purpose malloc implementation that performs better at memory usage than the standard malloc.&lt;br&gt;
Many benchmarks showed how much better your applications perform using jemalloc, I can also confirm that from my personal experience.&lt;br&gt;
Here are a few links that show the performance gain from using jemalloc:&lt;br&gt;
&lt;a href="https://engineering.binti.com/jemalloc-with-ruby-and-docker/"&gt;https://engineering.binti.com/jemalloc-with-ruby-and-docker/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://engineering.appfolio.com/appfolio-engineering/2018/2/1/benchmarking-rubys-heap-malloc-tcmalloc-jemalloc"&gt;https://engineering.appfolio.com/appfolio-engineering/2018/2/1/benchmarking-rubys-heap-malloc-tcmalloc-jemalloc&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/motive-eng/we-solved-our-rails-memory-leaks-with-jemalloc-5c3711326456"&gt;https://medium.com/motive-eng/we-solved-our-rails-memory-leaks-with-jemalloc-5c3711326456&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can set the new Ruby version for your local project or even on your entire environment using the local/global flags:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rbenv local 3.2.0&lt;br&gt;
rbenv global 3.2.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Don't forget to run the rehash command for rbenv:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rbenv rehash&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The last step is to ensure that everything went right. Check your ruby version this way:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby -v --yjit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With the --yjit option, we should get the following output:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby 3.2.0 (2022-12-25 revision a528908271) +YJIT [x86_64-darwin21]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The +YJIT shows that YJIT has been enabled in your Ruby 3.2.0 installation.&lt;/p&gt;

&lt;p&gt;Nice work!&lt;/p&gt;

&lt;p&gt;I hope this little tutorial will help you. :)&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>yjit</category>
    </item>
    <item>
      <title>Stimulus MultiSelect</title>
      <dc:creator>Vernes Pendić</dc:creator>
      <pubDate>Tue, 22 Nov 2022 15:54:39 +0000</pubDate>
      <link>https://dev.to/wizardhealth/stimulus-multiselect-4m8p</link>
      <guid>https://dev.to/wizardhealth/stimulus-multiselect-4m8p</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Every developer had to struggle with choosing the right plugin/package for things that are time consuming or have already been done in ways that suit their needs. Juggling 🤹‍♂️ between a package that is smaller in size or has certain features that we need can be frustrating.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkdxikye15f8pnsz4lbgt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkdxikye15f8pnsz4lbgt.gif" alt="Options" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what happens when there are no packages to choose from? On top of that, what if there is a feature that millions of developers need, but struggle to find answers or make custom solutions for every app they make.&lt;/p&gt;

&lt;p&gt;I am, of course, talking about the atrocious implementation of the multiple select feature built into every major browser 😫&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqc0t2qp53kjn9hasseni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqc0t2qp53kjn9hasseni.png" alt="Built-in multiple select" width="172" height="105"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftxxfq5ulbs09ce8rpgze.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftxxfq5ulbs09ce8rpgze.gif" alt="Crash" width="250" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;Since this frustrated my colleagues and me for a long time we decided to &lt;a href="https://github.com/WizardComputer/stimulus-multiselect" rel="noopener noreferrer"&gt;make our own implementation and open source&lt;/a&gt; it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ft992xuq7sf3u4he76np4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ft992xuq7sf3u4he76np4.gif" alt="Image description" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are not pioneers in this, naturally. There is many a plugin trying to solve the same problem. But what stuck with me when researching is none of them seem to quite scratch the perfectionist itch (now always a good thing 😅). Some of them require big dependencies like vue.js or jQuery, while some of them just lack the features or the ability to be customized.&lt;/p&gt;

&lt;h1&gt;
  
  
  Stimulus Multiselect
&lt;/h1&gt;

&lt;p&gt;You are going to &lt;strong&gt;need&lt;/strong&gt; &lt;a href="https://stimulus.hotwired.dev/" rel="noopener noreferrer"&gt;stimulus.js&lt;/a&gt; as a dependency for this package to work. It is a minimal, easy to understand javascript flavor for handling HTML.&lt;/p&gt;

&lt;p&gt;If you are using a js bundler with &lt;code&gt;node_modules&lt;/code&gt; support (such as esbuild, rollup.js or Webpack) install the package from npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @wizardhealth/stimulus-multiselect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using &lt;a href="https://github.com/rails/importmap-rails" rel="noopener noreferrer"&gt;importmap-rails&lt;/a&gt;, you'll need to pin &lt;code&gt;@wizardhealth/stimulus-multiselect&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;./bin/importmap pin @wizardhealth/stimulus-multiselect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Load your stimulus application as usual and the register the multiselect&lt;br&gt;
controller with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Multiselect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@wizardhealth/stimulus-multiselect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multiselect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Multiselect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The multiselect has many modes of working. You can fetch data remotely or load a static json collection of items. An example of this static approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"multiselect"&lt;/span&gt; &lt;span class="na"&gt;data-multiselect-items-value=&lt;/span&gt;&lt;span class="s"&gt;'[{ "value": "cuckoo", "text": "Cuckoo 🐦"}, { "value": "macaw", "text": "Macaw 🦜"}, { "value": "rooster", "text": "Rooster 🐓"}]'&lt;/span&gt; &lt;span class="na"&gt;data-placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search for birds..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;multiple=&lt;/span&gt;&lt;span class="s"&gt;"multiple"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"multiselect__hidden"&lt;/span&gt; &lt;span class="na"&gt;data-multiselect-target=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"form[test_ids][]"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"form_test_ids"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Let's build an app
&lt;/h1&gt;

&lt;p&gt;We are gonna build a Rails app (since Stimulus is mostly used with Rails) that has a backend of different sports. We are gonna search through these sports with the help of the multiselect and return the results back to show in the dropdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a new app &lt;code&gt;rails new multiselect_test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scaffold Sports so we can search through them &lt;code&gt;rails g scaffold Sport name:string&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Migrate it! &lt;code&gt;rails db:migrate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start up the server &lt;code&gt;rails s&lt;/code&gt; and get to creating some sports&lt;br&gt;
&lt;a href="https://media2.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%2Fag17bfv5fa7b0hrv57fb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fag17bfv5fa7b0hrv57fb.gif" alt="Creating sport" width="483" height="370"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the package &lt;code&gt;yarn add @wizardhealth/stimulus-multiselect&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The implementation
&lt;/h2&gt;

&lt;p&gt;We are going to use the sports#index page for testing. So we need to make the following changes to the controller and view.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are going to make use of a simple where for the purposes of this example. The index needs to like like this. The parameter that contains the search term from the select input is inside &lt;code&gt;params[:q]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
  &lt;span class="vi"&gt;@sports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Sport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"name LIKE ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:q&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The response that the select needs is JSON. So let's change the json response views that are inside &lt;code&gt;app/views/sports/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/views/sports/index.json.jbuilder&lt;/span&gt;

&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array!&lt;/span&gt; &lt;span class="vi"&gt;@sports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;partial: &lt;/span&gt;&lt;span class="s2"&gt;"sports/sport"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :sport&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The select needs a json that contains the &lt;strong&gt;value&lt;/strong&gt; (usually the id) and the &lt;strong&gt;text&lt;/strong&gt; value (what is shown when selecting)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/views/sports/_sport.json.jbuilder&lt;/span&gt;

&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt; &lt;span class="n"&gt;sport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="n"&gt;sport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Lastly, we need to put the select HTML somewhere. Let's use the &lt;code&gt;sports/index.html.erb&lt;/code&gt; for this
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/sports/index.html.erb --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"multiselect"&lt;/span&gt; &lt;span class="na"&gt;data-multiselect-search-url-value=&lt;/span&gt;&lt;span class="s"&gt;"/sports"&lt;/span&gt; &lt;span class="na"&gt;data-placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search for sports..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;multiple=&lt;/span&gt;&lt;span class="s"&gt;"multiple"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"multiselect__hidden"&lt;/span&gt; &lt;span class="na"&gt;data-multiselect-target=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sports[]"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"sport_ids"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add the contents of &lt;a href="https://github.com/WizardComputer/stimulus-multiselect/blob/main/src/multiselect.css" rel="noopener noreferrer"&gt;this file&lt;/a&gt; to your css
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* app/assets/stylesheets/application.css */&lt;/span&gt;

&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;The&lt;/span&gt; &lt;span class="nt"&gt;css&lt;/span&gt; &lt;span class="nt"&gt;contents&lt;/span&gt; &lt;span class="nt"&gt;from&lt;/span&gt; &lt;span class="nt"&gt;the&lt;/span&gt; &lt;span class="nt"&gt;file&lt;/span&gt; &lt;span class="nt"&gt;mention&lt;/span&gt; &lt;span class="nt"&gt;above&lt;/span&gt; &lt;span class="nt"&gt;go&lt;/span&gt; &lt;span class="nt"&gt;HERE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;When going to &lt;em&gt;localhost:3000/sports&lt;/em&gt; we should see this&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fr9yl1xeuq2d22zsulgqo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fr9yl1xeuq2d22zsulgqo.png" alt="Image description" width="577" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The end product
&lt;/h2&gt;

&lt;p&gt;Now just search any sport you like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fdav6el74k9f6mlnear52.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdav6el74k9f6mlnear52.gif" alt="Image description" width="565" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Stimulus Multiselect ❓
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Easy to set up&lt;/li&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WizardComputer/stimulus-multiselect#stimulus-multiselect-controller" rel="noopener noreferrer"&gt;Good documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Lot of options for loading data and handling selected items&lt;/li&gt;
&lt;li&gt;Design is customizable (css file is extracted so you can make the select suit your application look)&lt;/li&gt;
&lt;li&gt;Accessible&lt;/li&gt;
&lt;li&gt;Contributions and issue raising are welcome on &lt;a href="https://github.com/WizardComputer/stimulus-multiselect" rel="noopener noreferrer"&gt;our GitHub page&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The finish line 🔚
&lt;/h2&gt;

&lt;p&gt;Would love to know what you think. Comment, review the code, try the select and tell us how we can improve 💚&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj94cak3brw93gvmvajn3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj94cak3brw93gvmvajn3.gif" alt="Image description" width="306" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Rails snack - Upgrade to Ruby 3</title>
      <dc:creator>Vernes Pendić</dc:creator>
      <pubDate>Thu, 31 Mar 2022 09:02:58 +0000</pubDate>
      <link>https://dev.to/wizardhealth/rails-snack-upgrade-to-ruby-3-5f6a</link>
      <guid>https://dev.to/wizardhealth/rails-snack-upgrade-to-ruby-3-5f6a</guid>
      <description>&lt;p&gt;There are a &lt;a href="https://www.fastruby.io/blog/ruby/upgrades/upgrade-ruby-from-2.7-to-3.0.html"&gt;couple&lt;/a&gt; &lt;a href="https://reinteractive.com/posts/499-no-app-left-behind-upgrade-your-application-to-ruby-3-0-and-stay-on-the-upgrade-path"&gt;of&lt;/a&gt; &lt;a href="https://dev.to/michaelcurrin/upgrade-to-ruby-3-update-projects-9id"&gt;posts&lt;/a&gt; I found online for the upgrade of Ruby to version 3. Very few of them mentioning Rails and its issues during the upgrade.&lt;/p&gt;

&lt;p&gt;My versions prior to the upgrade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails &lt;span class="nt"&gt;-v&lt;/span&gt;
Rails 7.0.2.3

ruby &lt;span class="nt"&gt;-v&lt;/span&gt;
2.7.5

gem list
sidekiq &lt;span class="o"&gt;(&lt;/span&gt;6.2.2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm mentioning &lt;em&gt;sidekiq&lt;/em&gt; since it is the most commonly used background processing for Rails (and I had problems when updating 😅).&lt;/p&gt;

&lt;p&gt;The two problems I had (not mentioned anywhere):&lt;/p&gt;

&lt;p&gt;
  1. ActionCable.server.broadcast
  &lt;br&gt;
&lt;a href="https://github.com/rails/rails/issues/40993"&gt;This one&lt;/a&gt; went under the radar but without this change ActionCable won't work. Rails contributors &lt;a href="https://github.com/rails/rails/pull/41050"&gt;fixed the issue&lt;/a&gt; but here it is for everyone&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  2. Sidekiq (and gems connected to it)
  &lt;br&gt;
I had to upgrade sidekiq to the newest version because of the issue of log clutter. Specifically, &lt;a href="https://github.com/mperham/sidekiq/issues/5178#issuecomment-1029545859"&gt;this deprecation message&lt;/a&gt;. This has since been fixed (so update sidekiq). But not all gems connected to sidekiq have since caught up (sidekiq-statistic, sidekiq-cron... to mention a few). This is very annoying, especially for anyone using foreman, makes the logs unreadable. So keep an eye for updates if you are using any of these.&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;Would love for anyone who did the update to contribute with a comment below. Add any problems you had that were not mentioned anywhere so we can help as many people as possible in one place ❤️&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>upgrade</category>
      <category>rails</category>
    </item>
    <item>
      <title>Dynamically direct routes for polymorphic associations - Ruby on Rails</title>
      <dc:creator>Harun Sabljaković</dc:creator>
      <pubDate>Tue, 12 Oct 2021 12:01:28 +0000</pubDate>
      <link>https://dev.to/wizardhealth/dynamically-direct-routes-for-polymorphic-associations-5hhb</link>
      <guid>https://dev.to/wizardhealth/dynamically-direct-routes-for-polymorphic-associations-5hhb</guid>
      <description>&lt;p&gt;Have you ever struggled with polymorphic associations? We all have, don’t worry.&lt;br&gt;
Here’s an example of a polymorphic relationship.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;I’ve recently bumped into a problem where I had to list out all subjects (employees and products in this case) and when user interacted with one list item, it would redirect to that subject’s show page.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can see the problem, right? The obvious solution here would be to check the type of imageable and set the path helper accordingly. But, there’s a slightly more advanced technique for this use-case: direct method.&lt;br&gt;
In your routes.rb file simply add this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And now you can use imageable_path(imageable) as a path helper that will dynamically resolve to imageable’s show page.&lt;br&gt;
Now our example above becomes:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Aaaand voilà, we’ve got a path helper that resolves to any imageable show page without the need to manually check for the type of imageable.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Effortlessly install TailwindCss in a Rails app with Webpack (minimum configuration)</title>
      <dc:creator>Vernes Pendić</dc:creator>
      <pubDate>Sun, 22 Aug 2021 14:26:28 +0000</pubDate>
      <link>https://dev.to/wizardhealth/effortlessly-install-tailwindcss-in-a-rails-app-with-webpack-minimum-configuration-14gg</link>
      <guid>https://dev.to/wizardhealth/effortlessly-install-tailwindcss-in-a-rails-app-with-webpack-minimum-configuration-14gg</guid>
      <description>&lt;p&gt;A while back &lt;a href="https://twitter.com/dhh"&gt;DHH&lt;/a&gt; decided to created a &lt;a href="https://github.com/rails/tailwindcss-rails"&gt;gem&lt;/a&gt; for easily installing TailwindCss into rails apps 🙌🏻. This gem could be used to install Tailwind through the asset pipeline as well as using webpack. This &lt;a href="https://github.com/rails/tailwindcss-rails/issues/62#issuecomment-900193727"&gt;changed&lt;/a&gt; later on as contributors wanted to focus their attention to what was the heart of the gem 🥺.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d10dMmzqCYqQ0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d10dMmzqCYqQ0/giphy.gif" width="400" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, since a lot of people used this gem to get a new Rails app going with Tailwind without the hassle of configuring everything from scratch (including colleagues from my company), &lt;a href="https://dev.to/wizardhealth"&gt;we decided&lt;/a&gt; to create a &lt;a href="https://github.com/WizardComputer/tailwindcss-rails-webpacker"&gt;new gem&lt;/a&gt; 🎉. This gem installs Tailwind with Webpack and has production purging enabled. Other Webpack specific problems are to be addressed as well.&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>webpack</category>
      <category>rails</category>
      <category>gem</category>
    </item>
    <item>
      <title>Meza: Extract text from file</title>
      <dc:creator>Sinan Mujan</dc:creator>
      <pubDate>Thu, 16 Jan 2020 13:52:20 +0000</pubDate>
      <link>https://dev.to/wizardhealth/meza-extract-text-from-file-5h9b</link>
      <guid>https://dev.to/wizardhealth/meza-extract-text-from-file-5h9b</guid>
      <description>&lt;p&gt;If you ever have a situation where you have a huge file and want to extract a certain portion from this file (e.g. a log file or database dump), you can use the &lt;strong&gt;sed&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;Sed is a &lt;em&gt;stream editor&lt;/em&gt; that is used to perform basic text transformations on a file or input stream.&lt;/p&gt;

&lt;p&gt;👇&lt;/p&gt;

&lt;p&gt;Extract between two patterns (or words):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;sed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="s1"&gt;'/beginning_pattern/,/end_pattern/p'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Extract from a pattern (word) to the end of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;sed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="s1"&gt;'/beginning_pattern/,$p'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For more information about sed, check out this &lt;a href="https://www.gnu.org/software/sed/manual/sed.html"&gt;link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>productivity</category>
      <category>commandline</category>
    </item>
    <item>
      <title>Tailwind CSS</title>
      <dc:creator>Vernes Pendić</dc:creator>
      <pubDate>Mon, 02 Dec 2019 14:49:36 +0000</pubDate>
      <link>https://dev.to/wizardhealth/tailwind-css-29p3</link>
      <guid>https://dev.to/wizardhealth/tailwind-css-29p3</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;When creating a new website within a tiny amount of time or with a small development team most people look towards Bootstrap to help with the design. Taking into account the ease of use, an abundance of documentation and plenty of predefined css components it is not a mystery why Bootstrap is so popular. &lt;/p&gt;

&lt;p&gt;However, when the project gets bigger and more users start using the application concerns of page load and developer performance arise. While using Bootstrap it is very unlikely that all available utility classes are going to be used resulting in a considerable amount of css bloat as well as unused components. &lt;strong&gt;Enter Tailwind&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gDacVBBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/tqpthh0cv88anxyg48m0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gDacVBBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/tqpthh0cv88anxyg48m0.gif" alt="Alt Text" width="360" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tailwind is a CSS framework for rapid-fire UI development. When mentioning CSS frameworks first thing that comes to mind is Bootstrap, Material Design or even Bulma. However, even though Tailwind is considered a framework it doesn't fit under the same philosophy as the others. Tailwind is primarily a utility 🛠 framework or rather a utility bundle. &lt;/p&gt;

&lt;p&gt;Tailwind doesn't provide a default theme or any predefined UI components. Also, with Tailwind, it is rather unlikely to get two similarly looking pages. This is due to there being no imposed design decisions (like with vanilla css, the limit is our imagination).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/QIiqoufLNmWo8/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QIiqoufLNmWo8/giphy.gif" alt="imagination" width="360" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tailwind provides tools for rapid development 🏃🏼‍♀️💨, while at the same time allowing the developer to maintain identity. Even though there is no limit to imagination with Tailwind, designing is structured in a way so that the developer can make a self-imposed ruleset to avoid css bloat or repeated properties (i.e. making 10 colors that all look similar).&lt;/p&gt;

&lt;p&gt;There are three main approaches when CSS and UI design is in question. Every one of them has pros and cons shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nibdMaey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/k3jyat7uk26fx5j9x780.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nibdMaey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/k3jyat7uk26fx5j9x780.png" alt="comparison" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The table above has an error in the Utility frameworks column. The error is that it suggests that the Utility frameworks have "Little Control" which is not true in the case of Tailwind because inside it everything is configurable.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Utility classes
&lt;/h1&gt;

&lt;p&gt;When taking into account that the main goal of Tailwind is not providing users predefined components but tools for rapid component development it is clear why we won't find a ".btn" class like in Bootstrap. Instead, we will find utility classes. All predefined utility classes can be found in the &lt;a href="https://tailwindcss.com/"&gt;official documentation&lt;/a&gt; and in the configurable javascript file &lt;em&gt;tailwind.config.js&lt;/em&gt; in the root of the project after &lt;a href="https://gorails.com/episodes/tailwind-css-framework-with-rails"&gt;installation&lt;/a&gt;. Every available class can be configured for individual purposes or the purposes of a larger project. An example of styling a button using tailwind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex h-screen justify-center items-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-green-500 p-3 border-2 outline-none border-black rounded"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Adam
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vs Bootstrap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex justify-content-center align-items-center"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 100vh;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Adam&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tailwind CSS&lt;/th&gt;
&lt;th&gt;Bootstrap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wFBMr8PN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xcoghnwme8e5jv1gvky1.png" alt="" width="626" height="418"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qgXIizm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pfg7uehpmkd9qgxiipje.png" alt="" width="538" height="388"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Using Bootstrap a predefined button design is achieved. To achieve a custom look we need to write custom css. While using utility classes it is possible to achieve any look and feel of the button &lt;strong&gt;without writing any css&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is important for reasons below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There won't be 10 different colors that look the same&lt;/li&gt;
&lt;li&gt;The application will have a uniform look (i.e. same padding for lists or containers)&lt;/li&gt;
&lt;li&gt;The ability to create a personal UI design, identity, branding without writing a bunch of custom CSS (we don't have to be CSS experts)&lt;/li&gt;
&lt;li&gt;Speed 🏎🏎🏎💨💨💨&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Utility first 🥇
&lt;/h1&gt;

&lt;p&gt;In the above example of the button, there is a large number of added classes in order to achieve the wanted look. One of the reasons for this is the recommended way of creating components, and that is the utility first method. In short, this means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add an appropriate HTML element&lt;/li&gt;
&lt;li&gt;Add appropriate utility classes&lt;/li&gt;
&lt;li&gt;Profit 💰?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method achieves the main goal of Tailwind: Rapid UI development. This means making the UI components look as intended without adding any custom styling. Of course, sometimes it is inevitable to write CSS, but with this approach, it is reduced to a minimum.&lt;/p&gt;

&lt;p&gt;Looking at the above mentioned button example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-green-500 p-3 border-2 outline-none border-black rounded"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Adam
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing that immediately sticks out is the number of classes needed to create this button. Sometimes it looks unreadable and seems like clutter. This is a problem when taken into account real scenarios in which there might be multiple buttons or other repeating components on the same page.&lt;/p&gt;

&lt;h1&gt;
  
  
  Extracting components
&lt;/h1&gt;

&lt;p&gt;Extracting components is a process of extracting utility classes into new, clearly defined and readable classes. Two things give meaning to this process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The problem of bloating HTML with utility classes&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns"&gt;Separation of concerns&lt;/a&gt; or reusable components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, when looking at the above mention button, there is no need to extract the utility classes into a new class if we are looking at the button as a single occurring component. However, if we look at the button in the context of a bigger project which will certainly have more than one similarly or identically looking button then copying a large number of utility classes seems like an unnecessary obstacle. Besides, if there is a need to change the style of a certain UI component that is repeated it would be a major problem.&lt;/p&gt;

&lt;p&gt;How to extract utility classes? Tailwind gives us a very useful function for this: "@apply". In the example below we have the CSS for the same button as above but with extracted classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn-wizard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Adam&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.btn-wizard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;bg-green-500&lt;/span&gt; &lt;span class="err"&gt;p-3&lt;/span&gt; &lt;span class="err"&gt;border-2&lt;/span&gt; &lt;span class="err"&gt;outline-none&lt;/span&gt; &lt;span class="err"&gt;border-black&lt;/span&gt; &lt;span class="err"&gt;rounded;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wFBMr8PN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xcoghnwme8e5jv1gvky1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wFBMr8PN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xcoghnwme8e5jv1gvky1.png" alt="" width="626" height="418"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;As you can see the output is the same as before, but the HTML is cleaner and more readable. The .btn-wizard class can now be used multiple times across the website.&lt;/p&gt;
&lt;h1&gt;
  
  
  Responsiveness
&lt;/h1&gt;

&lt;p&gt;Every Tailwind utility class has its responsive behaviour. This allows for effortless creation of responsive components without writing additional CSS. Tailwind provides a simple method of putting already existing utility classes into a responsive context. Using the prefix {screen}:{class}. If we look at the above example of the button and want to change its color depending on the screen size (i.e. if it is a monitor, laptop or mobile screen) we have to add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-green-500 sm:bg-red-500 p-3 border-2 outline-none border-black rounded"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Dagi
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will get the appropriate &lt;a href="https://recordit.co/ymvDq7hBhQ"&gt;output&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tailwind responsiveness implies that the page is going to be created for mobile screens &lt;strong&gt;first&lt;/strong&gt;. Adding the sm:bg-red-500 tells the background of the element changes to red if the size of the screen is larger than the predefined value (which is configurable). If the size of the screen is smaller than the size which the "sm:" represents the colors of the background go back to the default, in this case, green.&lt;/p&gt;

&lt;p&gt;There are a couple of predefined screen size options in Tailwind:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---6Pu3a1F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lql1si0z1uc6gi8hsnlz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---6Pu3a1F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lql1si0z1uc6gi8hsnlz.png" alt="Alt Text" width="276" height="73"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Flexbox
&lt;/h1&gt;

&lt;p&gt;When comparing the responsiveness of Tailwind and Bootstrap there is one convenience lacking in Tailwind. That's the Grid functionality that we are so used to with Bootstrap. Tailwind doesn't come with predefined grid classes but provides the tools to achieve the same thing using &lt;a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/"&gt;Flexbox&lt;/a&gt; (&lt;a href="https://www.youtube.com/watch?v=JJSoEo8JSnc%5D"&gt;additional resource&lt;/a&gt;) and Tailwind width utility. An example of a grid using a combination of flexbox and tailwind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex h-64"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/2 bg-grey-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/2 bg-pink-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-16"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex h-64"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/3 bg-grey-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/3 bg-pink-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/3 bg-grey-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wTAe4FgJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ugvo6viylzlt9w9kt7oo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wTAe4FgJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ugvo6viylzlt9w9kt7oo.png" alt="Alt Text" width="880" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The divs above are completely responsive. It is possible to create an endless amount of columns while Bootstraps grid is limited to 12.&lt;/p&gt;

&lt;p&gt;Elements inside the div that have &lt;em&gt;display: flex;&lt;/em&gt; follow the x or y-axis for direction (x is the default). This means that the direction of elements inside the flex div can be changed by adding a simple "flex-col" class. This changes the above example to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex h-64"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/2 bg-grey-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-1/2 bg-pink-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-16"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-6 bg-grey-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-6 bg-pink-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-6 bg-grey-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lw3p_9ay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yrfo8j3zy5xa0vqojd6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lw3p_9ay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yrfo8j3zy5xa0vqojd6c.png" alt="Alt Text" width="880" height="285"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Configurability
&lt;/h1&gt;

&lt;p&gt;One of the biggest strengths of Tailwind is its configurability. In the center of every Tailwind project is the tailwind.config.js JavaScript file located in the root of the project (by default). It contains all the configurable utility classes and colors. &lt;strong&gt;This file doesn't exist unless the user opts to generate it&lt;/strong&gt;. If there is no config file the utility classes are the same as mentioned in the official documentation.&lt;/p&gt;

&lt;p&gt;By default, Tailwind provides a very useful configuration with predefined values to start with. These values are fully configurable and are not required to be used. The documentation, as well as the creator of Tailwind, encourages changing the default values to fit the individual design needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;Unlike other CSS frameworks, the Tailwind configuration is not co-dependent. This means that any utility class can be deleted without affecting the rest of the configuration&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The configuration file is divided into parts depending on the CSS options it affects. The example bellow shows how a set of utility classes looks for the height property and how to use it inside HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="cm"&gt;/*
  |-----------------------------------------------------------------------------
  | Height                                  https://tailwindcss.com/docs/height
  |-----------------------------------------------------------------------------
  |
  | Here is where you define your height utility sizes. These can be
  | percentage based, pixels, rems, or any other units. By default
  | we provide a sensible rem based numeric scale plus some other
  | common use-cases. You can, of course, modify these values as
  | needed.
  |
  | Class name: .h-{size}
  | CSS property: height
  |
  */&lt;/span&gt;

  &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.25rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.75rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.25rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;48&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of the configuration for the height property there is a short example of how to use the utility. In order to set the height to '4rem' inside HTML we will add the "h-16" class to the element. If inside the configuration we don't have the desired value, lets say '1.75rem' we can add it and name it however we please. Following the already set pattern it would make sense to call this value '7', but you can use whatever you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="cm"&gt;/*
  |-----------------------------------------------------------------------------
  | Height                                  https://tailwindcss.com/docs/height
  |-----------------------------------------------------------------------------
  |
  | Here is where you define your height utility sizes. These can be
  | percentage based, pixels, rems, or any other units. By default
  | we provide a sensible rem based numeric scale plus some other
  | common use-cases. You can, of course, modify these values as
  | needed.
  |
  | Class name: .h-{size}
  | CSS property: height
  |
  */&lt;/span&gt;

  &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.25rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.75rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.25rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.75rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//&amp;lt;------This was added&lt;/span&gt;

    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;48&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of the configuration file there is a colour section. It doesn't affect the generated CSS, but provides a way of centralising all colours without the need for a separate file containing only colours. The colours can be used with every utility with which it makes sense to use them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nx"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transparent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt; 
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt; 
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nx"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f7fafc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#edf2f7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#e2e8f0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#cbd5e0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#a0aec0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#718096&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#4a5568&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#2d3748&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#1a202c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nx"&gt;red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff5f5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fed7d7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#feb2b2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fc8181&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f56565&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#e53e3e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#c53030&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#9b2c2c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#742a2a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nx"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fffaf0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#feebc8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fbd38d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f6ad55&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ed8936&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#dd6b20&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

 &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, looking at the button we created, if we want to change its colour to be a bit darker we can use one of the following colours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-red-700 p-3 border-2 outline-none border-black rounded"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Adam
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;It is simple, professionally made, well documented and worth your try. It certainly made my workflow faster, made my UI more uniform and reduced the amount of CSS I wrote over the course of using it. None of my web pages using Tailwind look the same. Additionally, the &lt;a href="https://adamwathan.me"&gt;creator of Tailwind&lt;/a&gt; is an experienced guy in the industry and is continuously improving Tailwind. He also wrote a &lt;a href="https://refactoringui.com/book"&gt;useful book&lt;/a&gt; for anyone interested in design (highly recommend!).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;This post applies to the current version of Tailwind which at the time of writing is v.1.1.2.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=JJSoEo8JSnc"&gt;https://www.youtube.com/watch?v=JJSoEo8JSnc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCy1H38XrN7hi7wHSClfXPqQ"&gt;https://www.youtube.com/channel/UCy1H38XrN7hi7wHSClfXPqQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gorails.com/episodes/tailwind-css-framework-with-rails"&gt;https://gorails.com/episodes/tailwind-css-framework-with-rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.com/docs/"&gt;https://tailwindcss.com/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCy1H38XrN7hi7wHSClfXPqQ/videos"&gt;https://www.youtube.com/channel/UCy1H38XrN7hi7wHSClfXPqQ/videos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>tailwindcss</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Useful Heroku CLI commands</title>
      <dc:creator>Sinan Mujan</dc:creator>
      <pubDate>Tue, 19 Nov 2019 08:48:36 +0000</pubDate>
      <link>https://dev.to/wizardhealth/useful-heroku-cli-commands-2h03</link>
      <guid>https://dev.to/wizardhealth/useful-heroku-cli-commands-2h03</guid>
      <description>&lt;p&gt;Many of us use Heroku on a daily bases but are not aware of some interesting and useful CLI commands that may help you in your everyday work. Here we will take a look at some useful Heroku CLI commands.&lt;/p&gt;

&lt;h1&gt;
  
  
  heroku apps:info
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        app to run command against
  -j, --json
  -r, --remote=remote  git remote of app to use
  -s, --shell          output more shell friendly key/value pairs&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;If you want to check some basic information about your app that is running on Heroku, you can do so from your CLI. The command and output look something like this:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku apps:info -a name-of-your-app&lt;/b&gt;

&lt;i&gt;=== name-of-your-app
Addons:         heroku-postgresql:standard-0
                heroku-redis:premium-0
                timber-logging:free
Auto Cert Mgmt: false
Dynos:          web: 2, worker: 1
Git URL:        https://git.heroku.com/name-of-your-app.git
Owner:          owner@heroku.com
Region:         eu
Repo Size:      234 MB
Slug Size:      234 MB
Stack:          heroku-18
Web URL:        https://name-of-your-app.herokuapp.com/&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku buildpacks:search [term]
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;ARGUMENTS&lt;/b&gt;
  &lt;i&gt;TERM  search term that searches across name, namespace, and description&lt;/i&gt;

&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;--description=description  buildpack description to filter on

  --name=name                buildpack names to filter on using a comma
                             separated list

  --namespace=namespace      buildpack namespaces to filter on using a comma
                             separated list&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;You probably know that you can add or remove buildpacks but one useful command is the buildpack search command. Let's say you want to search for the &lt;strong&gt;elastic&lt;/strong&gt; buildpack, you can find it easily:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku buildpacks:search elastic&lt;/b&gt;

&lt;i&gt;Buildpack                                   Category  Description
──────────────────────────────────────────  ────────  ───────────────────────────────────
doctolib/heroku-buildpack-ci-elasticsearch  tools     Installs an in-dyno ElasticSearch …

1 buildpack found&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;Then you can eventually add the buildpack you just found and see that it is added to the bottom of your buildpacks list. One thing to notice is that this newly added buildpack will be applied to your app the next time you deploy, not instantly:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku buildpacks:add doctolib/heroku-buildpack-ci-elasticsearch -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Buildpack added. Next release on your-app-name will use:
  1. heroku/nodejs
  2. https://github.com/mojodna/heroku-buildpack-jemalloc
  3. heroku/ruby
  4. doctolib/heroku-buildpack-ci-elasticsearch&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku ci
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app            app name
  -p, --pipeline=pipeline  name of pipeline
  --json                   output in json format
  --watch                  keep running and watch for new and update tests&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;If you want to check the latest test runs for a given app or pipeline, you can do so with this command:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ci -a name-of-your-app&lt;/b&gt;

&lt;i&gt;=== Showing latest test runs for the lab pipeline
✓  2961  last_commit                fbe70c8  succeeded
✓  2960  second_commit              4615132  succeeded
✗  2959  first_commit               a3563a9  failed&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku:ci debug
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app            app to run command against
  -p, --pipeline=pipeline  pipeline
  -r, --remote=remote      git remote of app to use
  --no-cache               start test run with an empty cache
  --no-setup               start test dyno without running test-setup&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;One problem that some of you might have seen is tests that pass locally but fail on your Heroku CI. This command opens a new debug test run. This enables you to inspect the Heroku CI environment and the execution of tests inside a test dyno. It will first start the test setup script (if one is present) and then open a new terminal window from inside the new debug dyno, so you can run your tests from inside the CI.&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ci:debug -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Preparing source... done
Creating test run... done
Running setup and attaching to test dyno...
...
~ $&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku config:edit [key]
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;ARGUMENTS&lt;/b&gt;
  &lt;i&gt;KEY  edit a single key&lt;/i&gt;

&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against
  -r, --remote=remote  git remote of app to use&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;If you want to quickly edit a config variable that you have in your app, this is a great way. It opens the default text editor set by $VISUAL or $EDITOR. After editing and saving your file, you will be asked to confirm your edit by typing "yes" at the prompt.&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku config:edit APP_DISTRIBUTOR -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Fetching config... done

Config Diff:
APP_DISTRIBUTOR=test
APP_DISTRIBUTOR=test-new

Update config on ⬢ name-of-your-app with these values?:
Update config on ⬢ name-of-your-app with these values?: yes
Updating config... done&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku ps:scale
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against
  -r, --remote=remote  git remote of app to use&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;To resize your dynos you can use the ps:scale option. If you enter the command without any options you will see the current dyno formation:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ps:scale -a name-of-your-app&lt;/b&gt;

&lt;i&gt;console=0:Standard-1X rake=0:Standard-1X release=0:Standard-1X web=2:Standard-1X worker=1:Standard-1X&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;Let's say you want to scale your worker count up, you can do this in 2 ways:&lt;/p&gt;

&lt;p&gt;1.&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ps:scale worker=2:Standard-1X -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Scaling dynos... done, now running worker at 2:Standard-1X&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;2.&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ps:scale worker+1 -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Scaling dynos... done, now running worker at 2:Standard-1X&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;The same goes for scaling down, you can type the exact dyno formation you want or you can decrease it with the dash ( - ) sign.&lt;/p&gt;

&lt;h1&gt;
  
  
  heroku logs
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against

  -d, --dyno=dyno      only show output from this dyno type (such as "web" or
                       "worker")

  -n, --num=num        number of lines to display

  -r, --remote=remote  git remote of app to use

  -s, --source=source  only show output from this source (such as "app" or
                       "heroku")

  -t, --tail           continually stream logs

  --force-colors       force use of colors (even on non-tty output)&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;To check your application logs you can use the logs command. You can filter by dyno type, edit the number of lines you want to see, continually stream logs etc.&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku logs -n=4 -a name-of-your-app&lt;/b&gt;

&lt;i&gt;2019-11-04T13:34:02.024374+00:00 heroku[web.1]: Restarting
2019-11-04T13:34:02.097510+00:00 heroku[web.1]: State changed from up to starting
2019-11-04T13:34:02.191176+00:00 heroku[worker.1]: Restarting
2019-11-04T13:34:02.264730+00:00 heroku[worker.1]: State changed from up to starting&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku pg:backups:capture [database]
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app                  (required) app to run command against
  -r, --remote=remote            git remote of app to use
  -v, --verbose
  --wait-interval=wait-interval&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;To create a new database backup file, you can use this command. You have to enter the name of your database config variable (in this example it is HEROKU_POSTGRESQL_ORANGE_URL). You can find out the correct name for your database by checking the &lt;b&gt;&lt;i&gt;heroku config&lt;/i&gt;&lt;/b&gt; command. Then just enter the command like this:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:backups:create HEROKU_POSTGRESQL_ORANGE_URL -a name-of-your-app&lt;/b&gt;

 &lt;i&gt;▸    Continuous protection is already enabled for this database. Logical backups of large databases are likely to fail.
 ▸    See https://devcenter.heroku.com/articles/heroku-postgres-data-safety-and-continuous-protection#physical-backups-on-heroku-postgres.
Starting backup of add-on-name... done

Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.

Backing up ORANGE to b002... done&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;To download you newly created backup, first check the backup_id:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:backups -a name-of-your-app&lt;/b&gt;

&lt;i&gt;=== Backups
ID    Created at                 Status                               Size      Database
────  ─────────────────────────  ───────────────────────────────────  ────────  ────────
b002  2019-11-04 13:56:58 +0000  Completed 2019-11-04 14:02:24 +0000  397.92MB  ORANGE&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;and then you can download it:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:backups:download b002 -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Getting backup from ⬢ name-of-your-app... done, #2
Downloading latest.dump... ████████████████████████▏  100% 00:00 397.92MB&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku pg:bloat [database]
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against
  -r, --remote=remote  git remote of app to use&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;To show information about table and index bloat in your database, you can use this command:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:bloat HEROKU_POSTGRESQL_ORANGE_URL -a name-of-your-app&lt;/b&gt;

 &lt;i&gt;type  | schemaname |             object_name             | bloat |   waste    
-------+------------+-------------------------------------+-------+------------
 table | public     | table_1                             |   1.1 | 41 MB
 table | public     | table_2                             |   1.1 | 7360 kB
 table | public     | table_3                             |   1.1 | 4656 kB
 table | public     | table_4                             |   1.0 | 2480 kB&lt;/i&gt;  
&lt;/pre&gt;

&lt;p&gt;The &lt;b&gt;&lt;i&gt;bloat&lt;/i&gt;&lt;/b&gt; column shows the bloat factor, which is the fraction of the original table that exists as bloat. Because it is a ratio, there are no units. The &lt;b&gt;&lt;i&gt;waste&lt;/i&gt;&lt;/b&gt; column shows the total bloat (in bytes) in each table and index in the system.&lt;/p&gt;

&lt;h1&gt;
  
  
  heroku pg:psql [database]
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app            (required) app to run command against
  -c, --command=command    SQL command to run
  -f, --file=file          SQL file to run
  -r, --remote=remote      git remote of app to use
  --credential=credential  credential to use&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;You can access a psql shell of your database this way:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:psql HEROKU_POSTGRESQL_ORANGE_URL -a name-of-your-app&lt;/b&gt;

&lt;i&gt;--&amp;gt; Connecting to add-on-name
psql (11.3, server 11.5 (Ubuntu 11.5-1.pgdg16.04+1))
SSL connection (protocol: TLSv1.2, cipher: cipher-code, bits: 256, compression: off)
Type "help" for help.

name-of-your-app::HEROKU_POSTGRESQL_ORANGE=&amp;gt;&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;You can now query your database with standard SQL commands, do insert, update or delete statements if you need to.&lt;/p&gt;

&lt;h1&gt;
  
  
  heroku pg:pull source target
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app                            (required) app to run command against
  -r, --remote=remote                      git remote of app to use

  --exclude-table-data=exclude-table-data  tables for which data should be
                                           excluded (use ';' to split multiple
                                           names)&lt;/i&gt;

&lt;b&gt;DESCRIPTION&lt;/b&gt;
  &lt;i&gt;Pull from SOURCE into TARGET.

  TARGET must be one of:
     * a database name (i.e. on a local PostgreSQL server)  =&amp;gt; TARGET must not
  exist and will be created
     * a fully qualified URL to a local PostgreSQL server   =&amp;gt; TARGET must not
  exist and will be created
     * a fully qualified URL to a remote PostgreSQL server  =&amp;gt; TARGET must exist
  and be empty&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;This command can come in handy if your local database is not big enough but you want to test some feature. This way, you can copy a staging/production database to a new local database:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:pull HEROKU_POSTGRESQL_ORANGE_URL name_of_local_new_db -a name-of-your-app&lt;/b&gt;

&lt;i&gt;heroku-cli: Pulling add-on-name ---&amp;gt; name_of_local_new_db
...
heroku-cli: Pulling complete.&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;You can also do the opposite, to push one of your local databases to Heroku, with &lt;strong&gt;pg:push&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  heroku pipelines:diff
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against
  -r, --remote=remote  git remote of app to use&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;If you want to check if your staging and production app are in sync, you can do so with the &lt;strong&gt;pipelines:diff&lt;/strong&gt; command:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pipelines:diff -a name-of-your-staging-app&lt;/b&gt;

&lt;i&gt;Fetching apps from pipeline... done
Fetching release info for all apps... done

⬢ name-of-your-staging-app is up to date with ⬢ name-of-your-production-app&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;If they are not in sync, you will get a detailed commit diff with the differences:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pipelines:diff -a name-of-your-staging-app&lt;/b&gt;

&lt;i&gt;Fetching apps from pipeline... done
Fetching release info for all apps... done

=== ⬢ name-of-your-staging-app is ahead of ⬢ name-of-your-production-app by 2 commits
SHA      Date                  Author        Message
some-sha 2019-10-23T11:56:47Z  sinanmujan    Update Ruby version to 2.6.5
some-sha 2019-10-10T07:00:08Z  sinanmujan    Fix redirect middleware&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku ps
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against
  -r, --remote=remote  git remote of app to use
  --json               display as json&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;To get information about all the dynos in your application, their startup command and up time, you can do this:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ps -a name-of-your-app&lt;/b&gt;

&lt;i&gt;=== web (Standard-1X): jemalloc.sh bundle exec puma -C config/puma.rb (1)
web.1: up 2019/11/05 00:40:48 +0100 (~ 10h ago)

=== worker (Standard-1X): bundle exec sidekiq -e production -C config/sidekiq.yml (1)
worker.1: up 2019/11/04 17:44:06 +0100 (~ 17h ago)&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku ps:exec
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app        (required) app to run command against
  -d, --dyno=dyno      specify the dyno to connect to
  -r, --remote=remote  git remote of app to use
  --ssh                use native ssh
  --status             lists the status of the SSH server in the dyno&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;If you want to connect to one of your dynos through SSH, you can do so like this:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku ps:exec -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Establishing credentials... done
Connecting to web.1 on ⬢ name-of-your-app...
~ $&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  heroku redis:cli
&lt;/h1&gt;

&lt;pre&gt;
&lt;b&gt;OPTIONS&lt;/b&gt;
  &lt;i&gt;-a, --app=app          (required) app to run command against
  -c, --confirm=confirm
  -r, --remote=remote    git remote of app to use&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;You can access the Redis resource of your application:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku redis:cli -a name-of-your-app&lt;/b&gt;

&lt;i&gt;Connecting to redis-horizontal-35620 (REDIS_URL):
some-redis-url:20099&amp;gt;&lt;/i&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  Copy database between Heroku apps
&lt;/h1&gt;

&lt;p&gt;If you want to copy the entire database from one Heroku application to another, you can do it this way:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku pg:copy source_app::source_db_name destination_db_name -a destination_app&lt;/b&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  Copy ENV variables between Heroku apps
&lt;/h1&gt;

&lt;p&gt;If you want to copy ENV variables between 2 Heroku apps, there is an easy way to do this. First, we need to copy the settings from the current app to a text file on your local machine:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;heroku config -s -a existing-heroku-app &amp;gt; config.txt&lt;/b&gt;
&lt;/pre&gt;

&lt;p&gt;Then you can add the contents of this config file to your new Heroku app:&lt;/p&gt;

&lt;pre&gt;
&lt;b&gt;cat config.txt | tr '\n' ' ' | xargs heroku config:set -a new-heroku-app&lt;/b&gt;
&lt;/pre&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;These were just some interesting and hopefully helpful Heroku commands. You may find more useful tips and tricks in the official &lt;a href="https://devcenter.heroku.com/categories/reference"&gt;Heroku documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>ci</category>
      <category>webdev</category>
      <category>cli</category>
    </item>
    <item>
      <title>Meza: From PostgreSQL table to a JSON file</title>
      <dc:creator>Dino</dc:creator>
      <pubDate>Sun, 17 Nov 2019 10:21:01 +0000</pubDate>
      <link>https://dev.to/wizardhealth/meza-from-postgresql-table-to-a-json-file-54le</link>
      <guid>https://dev.to/wizardhealth/meza-from-postgresql-table-to-a-json-file-54le</guid>
      <description>&lt;p&gt;Ever wanted to export data from the PostgreSQL table into a JSON file?&lt;/p&gt;

&lt;p&gt;👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;pg_cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;copy (select row_to_json(r) from (select * FROM table_name) r ) to
table.json"&lt;/span&gt;
psql &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; host &lt;span class="nt"&gt;-U&lt;/span&gt; username &lt;span class="nt"&gt;-d&lt;/span&gt; database_name &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$pg_cmd&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/\\\\/\\/g'&lt;/span&gt; table.json &lt;span class="c"&gt;# clean up extra '\' characters&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;After executing these commands you will have two JSON files&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;table.json&lt;/strong&gt; - initial JSON exported data file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;table.json-e&lt;/strong&gt; - file which contains cleaned up JSON, without extra &lt;code&gt;\&lt;/code&gt; characters&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✌️&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>Introduction to Ruby blocks</title>
      <dc:creator>Dino</dc:creator>
      <pubDate>Tue, 12 Nov 2019 13:09:42 +0000</pubDate>
      <link>https://dev.to/wizardhealth/introduction-to-ruby-blocks-1ejc</link>
      <guid>https://dev.to/wizardhealth/introduction-to-ruby-blocks-1ejc</guid>
      <description>&lt;p&gt;Blocks are ubiquitous in Ruby. They are one of the defining and most powerful characteristics of the Ruby language.  It is almost impossible to write any meaningful Ruby code without the blocks. They appear everywhere from ruby core library methods such as enumerations to Rails to Rake to almost every gem out there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Core lib&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Ruby"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rails&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rake&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;ruby&lt;/span&gt; &lt;span class="s2"&gt;"test/unittest.rb"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Bundler&lt;/span&gt;
&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:development&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'pry-byebug'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Blocks, all over the place&lt;/em&gt; 😰😱&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/1yn20fhZcNhHV59YXz/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/1yn20fhZcNhHV59YXz/giphy.gif" alt="Blocks, everywere"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yet, they can be so hard to understand for beginners and even experienced programmers that are just starting with Ruby.&lt;/p&gt;

&lt;p&gt;In this post, we will look at what are the closures, blocks and basic usage patterns.&lt;/p&gt;

&lt;p&gt;Let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Scopes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lexical scope
&lt;/h3&gt;

&lt;p&gt;Lexical scope serves to answer one important question: &lt;strong&gt;What is the value of this variable at this line?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;
  &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"in the bottle"&lt;/span&gt;
  &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;speak&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "in the bottle"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we created a local variable inside the method, the variable is in the scope of the method, it is created there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"in the bottle"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;
  &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;speak&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; NameError (undefined local variable or method `message' for main:Object)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we created the variable outside the method scope. When we call the variable inside the method we get an error: &lt;strong&gt;Variable is out of the scope&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Local variables are tightly scoped, we can't access a variable outside itself unless it's passed as an argument, or we define an instance variable but that is a story for another day.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inherited scopes
&lt;/h3&gt;

&lt;p&gt;Yeah, yeah...we got it scoping rules explained above are nothing new and they are easy to grasp. But, wait how does this work then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"in the bottle"&lt;/span&gt;

&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# =&amp;gt; in the bottle&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; in the bottle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Blocks, Procs, Lambdas&lt;/strong&gt; are different. Blocks create scope between &lt;code&gt;do..end&lt;/code&gt;(same as method), but they inherit references to the local variables in the context where they are created.&lt;/p&gt;

&lt;p&gt;In our example we have 2 scopes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Outer/parent&lt;/strong&gt; - where variable &lt;code&gt;message&lt;/code&gt; is defined&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inner/child&lt;/strong&gt;  - scope inside the block&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our block is created in the context of parent scope and he will carry a reference to the local variable defined in that scope, thus making &lt;code&gt;message&lt;/code&gt; variable accessible from within the inner scope.&lt;/p&gt;

&lt;p&gt;When block calls variable from the outer/parent scope, that variable is called a &lt;strong&gt;free variable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Turns out, when function whose body(&lt;em&gt;lexical scope&lt;/em&gt;) references a variable(&lt;em&gt;free variable&lt;/em&gt;) that is declared in the parent scope we got a &lt;strong&gt;CLOSURE&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blocks
&lt;/h2&gt;

&lt;p&gt;Blocks are effectively a type of &lt;strong&gt;closure&lt;/strong&gt;. Blocks capture pieces of code that can be passed into methods to be executed later, they act like anonymous functions.&lt;/p&gt;

&lt;p&gt;The ability to encapsulate behavior into blocks and pass it to the methods is an extremely useful technique. This lets you &lt;strong&gt;separate general and specific pieces of your code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let us imagine we are developers for the NBA. We are building a register of the most popular players:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
    &lt;span class="vi"&gt;@team&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;
    &lt;span class="vi"&gt;@salary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;
    &lt;span class="vi"&gt;@age&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;players&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;palyers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Lebron James"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Lakers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;salary: &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age: &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;palyers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Kevin Durant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Nets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;salary: &lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age: &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;palyers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"James Harden"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Rockets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;salary: &lt;/span&gt;&lt;span class="mi"&gt;6000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age: &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a requirement to display players sorted by age or salary or name.&lt;/p&gt;

&lt;p&gt;Instead of tying our class with specific sorting implementation we can leverage the power of blocks and separating general from specific like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_by&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_by&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;salary&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_by&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Executing blocks
&lt;/h3&gt;

&lt;p&gt;Whenever you see &lt;code&gt;yield&lt;/code&gt; keyword that means execute the block, for example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;speak&lt;/code&gt; method will execute any block we give it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;speak&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Y"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; Y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we don't pass the block to the method, ruby will raise an exception.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;speak&lt;/span&gt; 
&lt;span class="c1"&gt;# =&amp;gt; LocalJumpError (no block given (yield))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luckily ruby gives as a nice way to check whether the block was passed with &lt;code&gt;block_given?&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;block_given?&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="s2"&gt;"No block is given"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;speak&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Y"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; Y &lt;/span&gt;

&lt;span class="n"&gt;speak&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; No block is given&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also pass arguments to the block to get similar behavior to this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ruby"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those with a sharp eye will notice that &lt;code&gt;message&lt;/code&gt; variable is a free variable here.&lt;/p&gt;

&lt;p&gt;That is all for now, in the next posts I will talk more about procs, lambdas, and interesting patterns that we can leverage procs, lambdas, and blocks for.&lt;/p&gt;

&lt;p&gt;✌️&lt;/p&gt;

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