<?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: Vinicius Stock</title>
    <description>The latest articles on DEV Community by Vinicius Stock (@vinistock).</description>
    <link>https://dev.to/vinistock</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F93182%2Fd00cc3f9-b0b1-4f76-af36-9456b4408de8.JPG</url>
      <title>DEV Community: Vinicius Stock</title>
      <link>https://dev.to/vinistock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vinistock"/>
    <language>en</language>
    <item>
      <title>Make a Ruby gem configurable</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Tue, 21 Jul 2020 13:32:50 +0000</pubDate>
      <link>https://dev.to/vinistock/make-a-ruby-gem-configurable-228d</link>
      <guid>https://dev.to/vinistock/make-a-ruby-gem-configurable-228d</guid>
      <description>&lt;p&gt;In the Ruby ecosystem, a well established way of customizing gem behavior is by using configuration blocks. Most likely, you came across code that looked 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="no"&gt;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some_lambda&lt;/span&gt; &lt;span class="o"&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;variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;do_important_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;variable&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This standard way of configuring gems runs once, usually when starting an application, and allows developers to tailor the gem's functionality to their needs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding the configuration block to a gem
&lt;/h1&gt;

&lt;p&gt;Let's take a look at how this style of configuration can be implemented. We'll divide our implementation in two steps: writing a configuration class and exposing it to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the configuration class
&lt;/h2&gt;

&lt;p&gt;The configuration class is responsible for keeping all the available options and their defaults. It is composed of two things: an initialize method where defaults are set and attribute readers/writers.&lt;/p&gt;

&lt;p&gt;Let's take a look at an example, where we can configure an animal and the sound that it makes. If the sound does not match the expected, we want to raise an error while configuring our gem. We'll then access what is configured for animal and sound and use it in our logic.&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;# lib/my_gem/configuration.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;MyGem&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt;
    &lt;span class="c1"&gt;# Custom error class for sounds that don't&lt;/span&gt;
    &lt;span class="c1"&gt;# match the expected animal&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnimalSoundMismatch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Animal sound map&lt;/span&gt;
    &lt;span class="no"&gt;ANIMAL_SOUND_MAP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"Dog"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Barks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"Cat"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Meows"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Writer + reader for the animal instance variable. No fancy logic&lt;/span&gt;
    &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:animal&lt;/span&gt;

    &lt;span class="c1"&gt;# Reader only for the sound instance variable.&lt;/span&gt;
    &lt;span class="c1"&gt;# The writer contains custom logic&lt;/span&gt;
    &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:sound&lt;/span&gt;

    &lt;span class="c1"&gt;# Initialize every configuration with a default.&lt;/span&gt;
    &lt;span class="c1"&gt;# Users of the gem will override these with their&lt;/span&gt;
    &lt;span class="c1"&gt;# desired values&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
      &lt;span class="vi"&gt;@animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dog"&lt;/span&gt;
      &lt;span class="vi"&gt;@sound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Barks"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Custom writer for sound.&lt;/span&gt;
    &lt;span class="c1"&gt;# If the sound variable is not exactly what is&lt;/span&gt;
    &lt;span class="c1"&gt;# mapped in our hash, raise the custom error&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;AnimalSoundMismatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"A &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@animal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; can't &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;sound&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;SOUND_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@animal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;sound&lt;/span&gt;

      &lt;span class="vi"&gt;@sound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sound&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exposing the configuration
&lt;/h2&gt;

&lt;p&gt;To expose the configuration means both letting users configure it and allowing the gem itself to read the value of each option.&lt;/p&gt;

&lt;p&gt;This is done with a singleton of our Configuration class and a few utility 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="c1"&gt;# lib/my_gem.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;MyGem&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="c1"&gt;# Instantiate the Configuration singleton&lt;/span&gt;
    &lt;span class="c1"&gt;# or return it. Remember that the instance&lt;/span&gt;
    &lt;span class="c1"&gt;# has attribute readers so that we can access&lt;/span&gt;
    &lt;span class="c1"&gt;# the configured values&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;configuration&lt;/span&gt;
      &lt;span class="vi"&gt;@configuration&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# This is the configure block definition.&lt;/span&gt;
    &lt;span class="c1"&gt;# The configuration method will return the&lt;/span&gt;
    &lt;span class="c1"&gt;# Configuration singleton, which is then yielded&lt;/span&gt;
    &lt;span class="c1"&gt;# to the configure block. Then it's just a matter&lt;/span&gt;
    &lt;span class="c1"&gt;# of using the attribute accessors we previously defined&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;configure&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;configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gem is now set to be configured by the applications that use 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="no"&gt;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# Notice that the config block argument&lt;/span&gt;
  &lt;span class="c1"&gt;# is the yielded singleton of Configuration.&lt;/span&gt;
  &lt;span class="c1"&gt;# In essence, all we're doing is using the&lt;/span&gt;
  &lt;span class="c1"&gt;# accessors we defined in the Configuration class&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Cat"&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Meows"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using the configuration in the gem
&lt;/h1&gt;

&lt;p&gt;Now that we have the customizable Configuration singleton, we can read the values to change behavior based on 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="c1"&gt;# lib/my_gem/make_sound.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;MyGem&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnimalSound&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
      &lt;span class="vi"&gt;@animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;animal&lt;/span&gt;
      &lt;span class="vi"&gt;@sound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sound&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;make_sound&lt;/span&gt;
      &lt;span class="s2"&gt;"The &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@animal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@sound&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using lambdas for configuration
&lt;/h1&gt;

&lt;p&gt;In specific scenarios, there may be a need for a configuration to not have a predetermined value, but rather to evaluate some logic as the application is running.&lt;/p&gt;

&lt;p&gt;For these cases, it is typical to define a lambda for the configuration value. Let's go through an example. The configuration class is similar to our previous case.&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;# lib/my_gem/configuration.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;MyGem&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt;
    &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:key_name&lt;/span&gt;

    &lt;span class="c1"&gt;# Define no lambda as the default&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
      &lt;span class="vi"&gt;@key_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Raise an error if trying to set the key_name&lt;/span&gt;
    &lt;span class="c1"&gt;# to something other than a lambda&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;key_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"The key_name must be a lambda"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Proc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="vi"&gt;@key_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can configure the lambda to whatever we need. You could even query the database if desired inside the lambda and return values from the app's models.&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;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lambda_config&lt;/span&gt; &lt;span class="o"&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;model_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"Post"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="ss"&gt;:posts&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:articles&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;Finally, the gem can use the lambda and get different results as the app is running.&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;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key_name&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Article"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:articles&lt;/span&gt;

&lt;span class="no"&gt;MyGem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key_name&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Post"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:posts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's about it for configuration blocks. Have you used this before to make your code/gems customizable? Do you know other strategies for configuring third party libraries? Let me know in the comments!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Changing Ruby classes at runtime with class_eval</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Fri, 10 Jul 2020 20:09:08 +0000</pubDate>
      <link>https://dev.to/vinistock/changing-ruby-classes-at-runtime-with-classeval-52m</link>
      <guid>https://dev.to/vinistock/changing-ruby-classes-at-runtime-with-classeval-52m</guid>
      <description>&lt;p&gt;One of Ruby's most interesting - and useful! - features is being able to change how classes and objects behave while your app is running.&lt;/p&gt;

&lt;p&gt;If you use Rails, then certainly you have used many runtime defined methods. Let's look at an example. Imagine a one to many association between two models: &lt;strong&gt;Author&lt;/strong&gt; and &lt;strong&gt;Post&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the author is already instantiated, then we can get the posts for this author by invoking&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;@author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="vi"&gt;@author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;posts&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;ActiveRecord::Associations::CollectionProxy [...]&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But where does the &lt;code&gt;posts&lt;/code&gt; method come from? This method is actually defined during runtime by the &lt;code&gt;has_many&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Author&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;:posts&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When reading the author model file, Ruby will invoke the &lt;code&gt;has_many&lt;/code&gt; methods passing the argument &lt;code&gt;:posts&lt;/code&gt; to it. Under the hood, &lt;code&gt;has_many&lt;/code&gt; will change the class that invoked it and add the association methods.&lt;/p&gt;

&lt;p&gt;This is possible thanks to the magic of &lt;code&gt;class_eval&lt;/code&gt;, a Ruby method designed to change the behavior of classes during runtime.&lt;/p&gt;

&lt;p&gt;It's a remarkable mean to provide shared functionality to classes in an elegant way that feels almost like you're just changing a configuration file.&lt;/p&gt;

&lt;h1&gt;
  
  
  How class_eval works
&lt;/h1&gt;

&lt;p&gt;There are two ways of using &lt;code&gt;class_eval&lt;/code&gt;: passing it a block or passing it a string with the changes we'd like to execute to the class. Let's look at them separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing a block
&lt;/h2&gt;

&lt;p&gt;When passing a block to &lt;code&gt;class_eval&lt;/code&gt;, it will evaluate that block within the context of the class that is invoking it.&lt;/p&gt;

&lt;p&gt;When passing blocks, it is very common to use &lt;code&gt;define_method&lt;/code&gt; for defining methods during runtime. It is a method itself that&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accepts the name of the new method as the argument&lt;/li&gt;
&lt;li&gt;Accepts a block to define the new method's body&lt;/li&gt;
&lt;li&gt;Yields the new method's regular arguments and block arguments to the body
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"name_of_new_method"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# Define the behavior of the new method.&lt;/span&gt;
  &lt;span class="c1"&gt;# arg1, arg2 and &amp;amp;block are accessible here in the body.&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, let's analyze an example where we want to add a &lt;code&gt;sing&lt;/code&gt; method to our classes. When invoked, it will define a method with the music genre for that class that just prints a string.&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;# Define the method sing. This method can be put&lt;/span&gt;
&lt;span class="c1"&gt;# wherever is convenient (e.g.: a module or a parent class)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# "Open" the class for changes&lt;/span&gt;
  &lt;span class="nb"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="c1"&gt;# Use the define_method method to define "rock"&lt;/span&gt;
    &lt;span class="c1"&gt;# in runtime&lt;/span&gt;
    &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;band&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;"I love &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;band&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="n"&gt;sing&lt;/span&gt; &lt;span class="ss"&gt;:rock&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# After evaluating the class, the new rock method exists&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;rock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"AC/DC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;I&lt;/span&gt; &lt;span class="n"&gt;love&lt;/span&gt; &lt;span class="no"&gt;AC&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;DC&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have our &lt;code&gt;rock&lt;/code&gt; method working!&lt;/p&gt;

&lt;p&gt;If we wanted to add methods to a class that do not depend on the argument passed to &lt;code&gt;sing&lt;/code&gt;, then a simple def inside the &lt;code&gt;class_eval&lt;/code&gt; block is another option.&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;sing&lt;/span&gt;
  &lt;span class="nb"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# This def is evaluate from the context of the class&lt;/span&gt;
    &lt;span class="c1"&gt;# so this will be defined in any class that invokes&lt;/span&gt;
    &lt;span class="c1"&gt;# sing&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;band&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;"I love &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;band&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="c1"&gt;# Notice the absence of the argument&lt;/span&gt;
  &lt;span class="n"&gt;sing&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;rock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Queen"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;I&lt;/span&gt; &lt;span class="n"&gt;love&lt;/span&gt; &lt;span class="no"&gt;Queen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Passing a string
&lt;/h2&gt;

&lt;p&gt;The second manner of using &lt;code&gt;class_eval&lt;/code&gt; is by passing it three arguments: a string with the Ruby that will be evaluated in the class, the file where it should be evaluated and the line where it should be evaluated.&lt;/p&gt;

&lt;p&gt;These two last arguments will typically always be the same, but they can be changed to achieve other types of behavior.&lt;/p&gt;

&lt;p&gt;The Ruby methods &lt;code&gt;__FILE__&lt;/code&gt; and &lt;code&gt;__LINE__&lt;/code&gt; are commonly used here and they return the current file and line being evaluated, respectively.&lt;/p&gt;

&lt;p&gt;Let's use this case as an example of how we could write &lt;code&gt;has_many&lt;/code&gt; using &lt;code&gt;class_eval&lt;/code&gt;. Notice that this is not the real implementation that Rails uses, but the general idea is similar.&lt;/p&gt;

&lt;p&gt;The usual manner to use the string version of &lt;code&gt;class_eval&lt;/code&gt; is to define a Ruby string with a HEREDOC and interpolate whatever data you need.&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;has_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# Turn current class name into name_id&lt;/span&gt;
  &lt;span class="c1"&gt;# E.g.: NewsLetter -&amp;gt; news_letter_id&lt;/span&gt;
  &lt;span class="c1"&gt;# Evaluated before opening class for modification&lt;/span&gt;

  &lt;span class="n"&gt;id_attribute_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;underscore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_id"&lt;/span&gt;

  &lt;span class="nb"&gt;class_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;ASSOCIATION_METHODS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__LINE__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
    def &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
      # Turn the argument (e.g.: :posts) into the class
      # name Post
      &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;singularize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;camelize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;.where(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id_attribute_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;: self.id)
    end
&lt;/span&gt;&lt;span class="no"&gt;  ASSOCIATION_METHODS&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 let's use this in a class and understand what the HEREDOC is evaluated to.&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;Author&lt;/span&gt;
  &lt;span class="c1"&gt;# Using our version of has_many&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:posts&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# In this case, the resource argument is :posts.&lt;/span&gt;
&lt;span class="c1"&gt;# The string resulting from the HEREDOC is the one below.&lt;/span&gt;
&lt;span class="c1"&gt;# Notice that this will get evaluated within the context&lt;/span&gt;
&lt;span class="c1"&gt;# of the Author class and then will define&lt;/span&gt;
&lt;span class="c1"&gt;# the instance method posts, allowing us to&lt;/span&gt;
&lt;span class="c1"&gt;# invoke&lt;/span&gt;
&lt;span class="c1"&gt;# author.posts &lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;posts&lt;/span&gt;
  &lt;span class="no"&gt;Post&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="ss"&gt;author_id: &lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&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;It's important to point out that many changes can be applied in a single invocation of &lt;code&gt;class_eval&lt;/code&gt;. For instance, the real implementation of &lt;code&gt;has_many&lt;/code&gt; in Rails would also provide the class with a setter. Both getter and setter can be defined at the same time.&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;@author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="vi"&gt;@author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;posts&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="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Using &lt;code&gt;class_eval&lt;/code&gt; enables developers to define behavior in runtime. This technique can be used to create methods with arguments and options passed in at a class level which results in an elegant organization of code.&lt;/p&gt;

&lt;p&gt;Have you used this before? Let me know some use cases in the comments!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Write your own Rails generators: the basics</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Mon, 29 Jun 2020 13:23:41 +0000</pubDate>
      <link>https://dev.to/vinistock/understanding-and-writing-rails-generators-10h1</link>
      <guid>https://dev.to/vinistock/understanding-and-writing-rails-generators-10h1</guid>
      <description>&lt;h1&gt;
  
  
  What generators are
&lt;/h1&gt;

&lt;p&gt;Rails generators are command line tools that are used for automating the process of creating or editing files with boiler plate code.&lt;/p&gt;

&lt;p&gt;In essence, they execute Ruby code much like a script and create or update files based on templates, user input and whatever logic necessary.&lt;/p&gt;

&lt;p&gt;If you've played around with Rails, surely they are not a completely foreign concept to you. Many useful generators come bundled with Rails.&lt;/p&gt;

&lt;p&gt;The model generator produces all files needed for a new model. It accepts a list of attributes and their respective types and generates files for the model, fixtures, migrations and unit tests.&lt;/p&gt;

&lt;p&gt;Another example is the controller generator. It spins up a new controller with a specified list actions - adding their respective routes to &lt;code&gt;config/routes.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Their purpose is to automate writing repetitive code that you would otherwise need to memorize or copy. Not only that, they help teams enforce standards for writing specific implementations as well as speeding up development.&lt;/p&gt;

&lt;p&gt;For a list of all generators defined within a given application, invoke generate (alias g) with no arguments. This includes generators from gems and from your own code base.&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;$ &lt;/span&gt;bin/rails g
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's dig a bit more into generators and then learn how to write a custom one for our own needs.&lt;/p&gt;

&lt;p&gt;We will split generators into two types: repeated use and one-off generators. While these names are not official, they will help convey the conceptual applicability of each one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeated use generators
&lt;/h2&gt;

&lt;p&gt;Repeated use generators are meant to be used multiple times whenever a developer is doing a specific task. The model generator mentioned earlier is a great example. A developer will create many models while working on an application and the generator can be used to achieve it every time.&lt;/p&gt;

&lt;p&gt;Let's examine an example on invoking the model generator.&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;$ &lt;/span&gt;bin/rails generate model User name age:integer group:references

invoke  active_record
    create    db/migrate/20191002201613_create_users.rb
    create    app/models/user.rb
    invoke    test_unit
    create      &lt;span class="nb"&gt;test&lt;/span&gt;/models/user_test.rb
    create      &lt;span class="nb"&gt;test&lt;/span&gt;/fixtures/users.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how this command can be broken down.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;bin/rails&lt;/code&gt; invokes the Rails executable CLI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generate&lt;/code&gt; is an argument for the Rails CLI telling it to invoke a generator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;model&lt;/code&gt; is an argument for the generate command and represents the name of the generator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;User&lt;/code&gt; is the first argument of the model generator, which is the name of the new model&lt;/li&gt;
&lt;li&gt;Finally, all the other arguments are attributes with their respective types for the model generator: &lt;code&gt;my_attribute:my_type&lt;/code&gt;. Omitting the attribute type defaults to a string&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repeated use generators are great for everyday tasks that simply require certain standards or are not worth memorizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  One-off generators
&lt;/h2&gt;

&lt;p&gt;One-off generators are procedures that need to run a single time to prepare a code base for some functionality. Typically, they are used to automate project configuration and gem installation, since these changes only need to be applied once.&lt;/p&gt;

&lt;p&gt;Gems or frameworks that require some sort of configuration in place to work properly will often provide these as install generators.&lt;/p&gt;

&lt;p&gt;A great example is the authentication framework &lt;a href="https://github.com/heartcombo/devise"&gt;Devise&lt;/a&gt;, which provides install generators to get an application ready to use its authentication features.&lt;/p&gt;

&lt;p&gt;For a shorter example (and a shameless plug), let's take a look at how to use the install generator of a gem of my own: &lt;a href="https://github.com/vinistock/sail"&gt;Sail&lt;/a&gt;. It is an engine for live configuration of applications and requires three things to work properly: a table for settings, a table for profiles and a config YAML file for declaring settings.&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="c"&gt;# user@~/workspace/my_awesome_rails_app&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;bin/rails g sail:install
      create  db/migrate/20191009202801_create_sail_settings.rb
      create  db/migrate/20191009202802_create_sail_profiles.rb
      create  config/sail.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the migrations, the app is ready to take advantage of all features provided by the engine. This type of generator is an outstanding way of providing a smooth experience for developers that want to use your gem.&lt;/p&gt;

&lt;p&gt;Instead of writing long docs on how to install your gem, consider providing an install generator that will set up their project for them. We can even make the generator ask for input from the developer to properly tailor the result to their needs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a custom generator
&lt;/h1&gt;

&lt;p&gt;For our convenience, one the generators bundled in Rails is the generator generator. That's right, a generator for creating other generators (after all, who would want to memorize all the boilerplate code for that?). Let's imagine we want to create a component generator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/rails g generator Component
      create  lib/generators/component
      create  lib/generators/component/component_generator.rb
      create  lib/generators/component/USAGE
      create  lib/generators/component/templates
      invoke  test_unit
      create    &lt;span class="nb"&gt;test&lt;/span&gt;/lib/generators/component_generator_test.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's zoom in into each file and explore why they exist.&lt;/p&gt;

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

&lt;p&gt;This file defines the usage instructions that will be displayed when invoking the generator with no arguments. This is how it looks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Description:
    Explain the generator

Example:
    bin/rails generate component Thing

    This will create:
        what/will/it/create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can change the copy to explain what the generator is supposed to do and what developers can expected from it. Invoking the generator with no arguments will then print the information we wrote.&lt;/p&gt;

&lt;p&gt;For our example, we will create a component generator that accepts the name of the component.&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;$ &lt;/span&gt;bin/rails g component

Description:
    Creates a component class

Example:
    bin/rails generate component MyComponent

    Creates the component class and unit &lt;span class="nb"&gt;test&lt;/span&gt;:
        app/components/my_component.rb
        &lt;span class="nb"&gt;test&lt;/span&gt;/components/my_component_test.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Component generator and its templates
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;lib/generators/component/component_generator.rb&lt;/code&gt; file defines the class that does all the magic. Here you can write whatever Ruby code is convenient to produce the output desired.&lt;/p&gt;

&lt;p&gt;This class automatically runs every method defined in it, so you can think that each method you define is a step of the generator. Not only that, every method defined will also be available for the generator's templates.&lt;/p&gt;

&lt;p&gt;Let's look at the generated Ruby file.&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;# lib/generators/component/component_generator.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComponentGenerator&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Generators&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NamedBase&lt;/span&gt;
  &lt;span class="n"&gt;source_root&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'templates'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__dir__&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;Currently, all the &lt;code&gt;ComponentGenerator&lt;/code&gt; does is define the source_root as the templates folder. Let's add a few things to it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The main step of evaluating the component template and creating the resulting file&lt;/li&gt;
&lt;li&gt;An example method that can be invoked from the template. In this case, it just returns a string&lt;/li&gt;
&lt;li&gt;A class collision check to prevent the accidental creation of files with a duplicate suffix (e.g.: MyComponentComponent)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/generators/component/component_generator.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComponentGenerator&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Generators&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NamedBase&lt;/span&gt;
  &lt;span class="n"&gt;source_root&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"templates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__dir__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;check_class_collision&lt;/span&gt; &lt;span class="ss"&gt;suffix: &lt;/span&gt;&lt;span class="s2"&gt;"Component"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_component_file&lt;/span&gt;
    &lt;span class="c1"&gt;# Template method&lt;/span&gt;
    &lt;span class="c1"&gt;# First argument is the name of the template&lt;/span&gt;
    &lt;span class="c1"&gt;# Second argument is where to create the resulting file. In this case, app/components/my_component.rb&lt;/span&gt;
    &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="s2"&gt;"component.rb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"app/components"&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;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

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

  &lt;span class="c1"&gt;# Example method that can be invoked from the template&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="s2"&gt;"some string"&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;And now let's create a template inside the templates folder. Again, notice how the methods we add to our generator class are accessible to the template (including the ones that are defined by the parent class &lt;code&gt;Rails::Generators::NamedBase&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/generators/component/templates/component.rb.tt&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= class_name %&amp;gt;Component
  def initialize
    @component_identifier =&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;%= my_method %&amp;gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, our generator is working and can create components with the desired name. It also makes use of our method that returns a string.&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;Running&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;

&lt;span class="no"&gt;Results&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="c1"&gt;# app/component/post_component.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostComponent&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@component_identifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"some string"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last file created for us is a unit test for the generator itself. Rails provides a parent class for generator unit tests which contains a variety of helper methods for verifying the functionality we wrote.&lt;/p&gt;

&lt;p&gt;Basically, we can assert which files are created and match against their contents.&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;ComponentGeneratorTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Generators&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_component_is_created&lt;/span&gt;
    &lt;span class="n"&gt;run_generator&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"my_component"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;assert_file&lt;/span&gt; &lt;span class="s2"&gt;"app/components/my_component.rb"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;assert_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/class MyComponent/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Next steps
&lt;/h1&gt;

&lt;p&gt;There's a lot more that we can do with generators. Accepting arguments with specific types, asking for user input as the generator is running and test framework hooks to create unit test files for our component while respecting the testing library of choice (e.g.: minitest vs rspec).&lt;/p&gt;

&lt;p&gt;I believed that including it all in a single article could be too dense. If the feedback is positive, I can turn this post into a series and explore more generator functionality. Please, let me know what you think in the comments!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Write a simple DSL in Ruby</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Tue, 24 Sep 2019 16:42:44 +0000</pubDate>
      <link>https://dev.to/vinistock/write-a-simple-dsl-in-ruby-1jgi</link>
      <guid>https://dev.to/vinistock/write-a-simple-dsl-in-ruby-1jgi</guid>
      <description>&lt;h1&gt;
  
  
  What is a DSL and what is it used for?
&lt;/h1&gt;

&lt;p&gt;A DSL (Domain Specific Language) can be thought of as a dialect built for a unique purpose. At the bottom, it is a set of functions that are made available to be used inside the given domain.&lt;/p&gt;

&lt;p&gt;The syntax used in the &lt;code&gt;Gemfile&lt;/code&gt;, &lt;code&gt;Rakefile&lt;/code&gt; or in tests written with &lt;code&gt;rspec&lt;/code&gt; are some examples of DSLs in the Ruby world. They aim to provide well-defined interfaces for their tasks - declaring dependencies, defining make like tasks and writing unit tests, respectively.&lt;/p&gt;

&lt;p&gt;Let's go through how one could go about creating a super minimalistic implementation of a &lt;a href="https://github.com/bundler/bundler"&gt;bundler&lt;/a&gt; like tool for read a Gemfile. Please notice that the intention is to grasp the concepts and not have a working version of a package manager by the end.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to create a DSL in Ruby
&lt;/h1&gt;

&lt;p&gt;Surprisingly (at least for me), it isn't complex to define your own DSL with Ruby. Quite the opposite in fact. In our package manager example, it involves the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating a class that defines all methods available in the DSL&lt;/li&gt;
&lt;li&gt;Reading the Gemfile&lt;/li&gt;
&lt;li&gt;Evaluating the Gemfile within the execution context of a given instance&lt;/li&gt;
&lt;li&gt;Using the evaluated information for installing the gems&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These steps may sound obscure at first, but sit tight and they will soon make sense. Let's begin by creating the DSL class implementation. This class will contain all the methods that will be available for the Gemfile.&lt;/p&gt;

&lt;p&gt;For simplicity, our DSL will only contain the &lt;code&gt;gem&lt;/code&gt; directive - used to add a dependency. The implementation for other methods such as &lt;code&gt;group&lt;/code&gt; or optional arguments such as &lt;code&gt;require: false&lt;/code&gt; will be left out for simplicity. However, the concepts presented here should be a good starting point to reach richer functionality.&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;# dsl.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dsl&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:gems&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="c1"&gt;# Initialize the list of gems&lt;/span&gt;
    &lt;span class="c1"&gt;# as an empty array.&lt;/span&gt;
    &lt;span class="vi"&gt;@gems&lt;/span&gt; &lt;span class="o"&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;def&lt;/span&gt; &lt;span class="nf"&gt;read_gemfile&lt;/span&gt;
    &lt;span class="c1"&gt;# Read the contents of the gemfile as a string.&lt;/span&gt;
    &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Gemfile"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Evaluate the Ruby string within the context&lt;/span&gt;
    &lt;span class="c1"&gt;# of the Dsl instance. That is, execute whatever&lt;/span&gt;
    &lt;span class="c1"&gt;# code found in the Gemfile using the state of&lt;/span&gt;
    &lt;span class="c1"&gt;# the current Dsl object.&lt;/span&gt;
    &lt;span class="nb"&gt;instance_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

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

  &lt;span class="c1"&gt;# Gem directive definition&lt;/span&gt;
  &lt;span class="c1"&gt;# Adds the given gem_name to the list of&lt;/span&gt;
  &lt;span class="c1"&gt;# gems to be installed.&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# This is the method executed whenever the Gemfile&lt;/span&gt;
  &lt;span class="c1"&gt;# contains the directive "gem 'something'"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gem_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@gems&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;gem_name&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 now have a minimal implementation of our Dsl class that can read the contents of the Gemfile and execute &lt;code&gt;gem&lt;/code&gt; directives by adding the gem names to the &lt;code&gt;@gems&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;All that is needed to add new directives to the DSL is creating new methods inside the DSL class. Every method in the class is made available to be used in our Gemfile. Furthermore, we can define a custom &lt;code&gt;method_missing&lt;/code&gt; to choose how we want to handle invocations that don't exist in our DSL.&lt;/p&gt;

&lt;p&gt;The extra succinct Gemfile below makes use of our &lt;code&gt;gem&lt;/code&gt; directive and also uses some regular Ruby code. Notice that because we're executing the contents of the Gemfile within the Dsl instance, any Ruby code is valid.&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;# Gemfile&lt;/span&gt;

&lt;span class="c1"&gt;# Add 'rails' to the list of gems in the Dsl class.&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"rails"&lt;/span&gt;

&lt;span class="c1"&gt;# Add 'rubocop' to the list of gems only if the environment&lt;/span&gt;
&lt;span class="c1"&gt;# variable RAILS_ENV matches 'development'.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"RAILS_ENV"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"development"&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"rubocop"&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 that we have our Dsl implementation and our example Gemfile, we can write some &lt;strong&gt;pseudo-code&lt;/strong&gt; that represents the much more complex installation process performed by &lt;a href="https://github.com/rubygems/rubygems"&gt;bundler&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create Dsl instance.&lt;/span&gt;
&lt;span class="n"&gt;dsl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dsl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;

&lt;span class="c1"&gt;# Read and evaluate the Gemfile populating&lt;/span&gt;
&lt;span class="c1"&gt;# the @gems variable.&lt;/span&gt;
&lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_gemfile&lt;/span&gt;

&lt;span class="c1"&gt;# For each defined gem, install it&lt;/span&gt;
&lt;span class="c1"&gt;# which usually involves download the code from&lt;/span&gt;
&lt;span class="c1"&gt;# the package registry (rubygems.org) and placing it&lt;/span&gt;
&lt;span class="c1"&gt;# inside the Ruby folder structure.&lt;/span&gt;
&lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;gem&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Bundler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install_gem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gem&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;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;That's all! I hope these few lines of code can shine a light on how easily a DSL can be created using Ruby. In the real world, DSLs can be much more complex, have a lot of elaborate syntax and numerous classes for achieving the full desired functionality.&lt;/p&gt;

&lt;p&gt;Additionally, there are many security implications we haven't covered in this article. Because this approach executes Ruby code from a string, we need to be extra careful with any user input that might end up being evaluated by the DSL. Otherwise, it could lead to remote code execution and cause all sorts of vulnerabilities.&lt;/p&gt;

&lt;p&gt;I hope this quick introduction provides enough context to play around and fosters interest around this topic. Let me know what you think in the comments. Have you written DSLs before?&lt;/p&gt;

&lt;h2&gt;
  
  
  Offtopic
&lt;/h2&gt;

&lt;p&gt;I would like to thank everyone who reads my articles. I just reached 2000 followers and I'm stoked!&lt;/p&gt;

&lt;p&gt;Be sure to also follow me on Twitter if you'd like bit sized programming comments or random pictures.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Before shipping a new feature</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Fri, 23 Aug 2019 22:28:58 +0000</pubDate>
      <link>https://dev.to/vinistock/before-shipping-a-new-feature-p28</link>
      <guid>https://dev.to/vinistock/before-shipping-a-new-feature-p28</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Shipping new features is exciting and as software developers, we want to see our code running in production. However, there are some actions, questions, and steps that one can take before delivering tasks that will help improve the quality of the new functionality.&lt;/p&gt;

&lt;p&gt;Acts, like building the code for graceful failures, taking advantage of refactoring opportunities, understanding the impact of the features being delivered, monitoring and manually testing the changes, are only a few examples pre-release activities.&lt;/p&gt;

&lt;h1&gt;
  
  
  Questions to ask before delivering a feature
&lt;/h1&gt;

&lt;p&gt;It is essential to always have in mind the impact new changes can potentially cause for the end customers. Reflect on what the consequences would be for the users if something went wrong regardless of how simple the commits being merged are.&lt;/p&gt;

&lt;p&gt;Also, reflect on how important the feature being delivered to the end-users is based on their perspective. How can it be made better?&lt;/p&gt;

&lt;p&gt;A few questions to ask before shipping our beloved code could be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What will the user experience if this page/service breaks?&lt;/p&gt;

&lt;p&gt;How difficult would it be to revert these changes?&lt;/p&gt;

&lt;p&gt;How big of an impact would a break like this have on our brand's image?&lt;/p&gt;

&lt;p&gt;What other features can leverage this one and deliver more value to our users?&lt;/p&gt;

&lt;p&gt;What functionality could be missing in this feature?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answers to questions like these will outline steps that can be taken to improve the quality of the shipped feature.&lt;/p&gt;

&lt;h1&gt;
  
  
  Before shipping checklist
&lt;/h1&gt;

&lt;p&gt;Here is a checklist of actions that can be done before clicking the deploy button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create tests for impactful corner cases
&lt;/h2&gt;

&lt;p&gt;Testing every single edge case is certainly not needed. You will most likely not cover all of them and it will get your test suite bloated.&lt;/p&gt;

&lt;p&gt;However, corner cases that lead to impactful failures must be tested and covered with fallback functionality. For example, if a specific page relies on fetching data from an external API. What happens if the API is down? Does the page break? Is it partially populated? Does it redirect to a different page?&lt;/p&gt;

&lt;p&gt;Exploring these most impactful edge scenarios will often prevent production headaches in the future. And if one slips through, reproduce the error in tests, fix the undesired behavior and then push it up the stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manually test changes
&lt;/h2&gt;

&lt;p&gt;Unfortunately, automated tests don't always catch everything. Take the time to explore the product and the new feature being delivered. Experience it as the customers would and ask yourself if you're satisfied with the solution.&lt;/p&gt;

&lt;p&gt;If improvements related to the feature are identified, make sure they are tracked with a user story. They might not need to be implemented right away, but if they are accessible in the backlog, eventually they will be worked on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get feedback from the customers
&lt;/h2&gt;

&lt;p&gt;We often have ideas and opinions on how the product we develop should be used. However, what truly matters is how our customers use and perceive the features we deliver.&lt;/p&gt;

&lt;p&gt;Getting feedback from end-users is a bittersweet feeling. It can be tough and insightful at the same time. They might criticize the product you worked hard to build while also giving you the knowledge of what they need or expect from it. Be open-minded and ready to shift focus if necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup adequate monitoring
&lt;/h2&gt;

&lt;p&gt;In software, a lot happens under the hood. It can be far from easy to tell if everything is fine just by playing around with the user interface. Logging is one of the ways used to peek into the system that is running in production and get a sense if things truly are fine.&lt;/p&gt;

&lt;p&gt;But what would you log? That is not a trivial question. It depends on the system, the product and the team building it. Too much logging might cause an unnecessary overhead while too little will give you zero context of what is happening in the application.&lt;/p&gt;

&lt;p&gt;Some examples of things to log are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When expected errors happen (e.g.: inside rescue/catch block)&lt;/li&gt;
&lt;li&gt;When an undesired, but necessary behavior occurs (e.g.: users are redirected to a 404 page)&lt;/li&gt;
&lt;li&gt;Key metrics (e.g.: number of items processed in the background)&lt;/li&gt;
&lt;li&gt;Business indicators (e.g.: number of users that signed up using Google)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Refactor code
&lt;/h2&gt;

&lt;p&gt;Stumbling upon pieces of code that could be refactored (for quality or reusability purposes) occurs frequently. Improving the code or making it reusable for other developers might cost a little bit of time now, but it will pay off in the long run.&lt;/p&gt;

&lt;p&gt;If no developer ever pays the price of refactoring any code, technical debt can pile up until the codebase will slow down the development of new features. At that point, you're paying the price of all the refactoring that wasn't done.&lt;/p&gt;

&lt;p&gt;If a section of the code can be improved with some extra work, do it. Make the next developer that will touch that part of the code happier.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This is my take on a feature release checklist. What would you add to the list? What practices do you have in your teams? I'd love to hear it!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Creating Ruby native extensions</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Tue, 09 Apr 2019 02:13:23 +0000</pubDate>
      <link>https://dev.to/vinistock/creating-ruby-native-extensions-kg1</link>
      <guid>https://dev.to/vinistock/creating-ruby-native-extensions-kg1</guid>
      <description>&lt;h1&gt;
  
  
  Note
&lt;/h1&gt;

&lt;p&gt;Since the time this post was written, the &lt;code&gt;ext&lt;/code&gt; option has been added to bundler, which automatically configures a new gem to be a native extension. Instead of following the outdated steps in this article, simply create the new gem using the &lt;code&gt;ext&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle gem my_gem &lt;span class="nt"&gt;--ext&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  What native extensions for Ruby are
&lt;/h1&gt;

&lt;p&gt;When programming in Ruby, our code is compiled into instructions and then executed by the Ruby virtual machine (which is built in C). &lt;/p&gt;

&lt;p&gt;Ruby native extensions are libraries written in C using the built-in functions of the RubyVM. Basically, it's C programming with a ton of functions and macros to interact with the virtual machine. Anything that can be achieved by using pure Ruby can also be implemented using the built-in instructions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why they are useful
&lt;/h1&gt;

&lt;p&gt;Native extensions have a significant performance advantage when compared to pure Ruby, making them an excellent alternative for heavy load processing. Additionally, they permit tailored memory management thanks to having access to C functions like &lt;code&gt;malloc&lt;/code&gt; and &lt;code&gt;free&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A variety of popular gems are native extensions. When running bundle install, any gem that prints out "building native extensions" to the console is one of them. Some examples are: &lt;a href="https://github.com/sparklemotion/nokogiri"&gt;nokogiri&lt;/a&gt;, &lt;a href="https://github.com/brianmario/mysql2"&gt;mysql2&lt;/a&gt; and &lt;a href="https://github.com/brianmario/yajl-ruby"&gt;yajl-ruby&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to create a native extension
&lt;/h1&gt;

&lt;p&gt;Let's walk through the steps for creating a native extension from scratch.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating the gem&lt;/li&gt;
&lt;li&gt;Gemspec configurations&lt;/li&gt;
&lt;li&gt;Adding the compile task&lt;/li&gt;
&lt;li&gt;The extconf file&lt;/li&gt;
&lt;li&gt;Creating the C extension&lt;/li&gt;
&lt;li&gt;Requiring the shared object&lt;/li&gt;
&lt;li&gt;Testing the extension&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Creating the gem
&lt;/h2&gt;

&lt;p&gt;The first step is generating the gem. The &lt;code&gt;bundle gem&lt;/code&gt; command encapsulates that task. In this case, our example gem is called "super".&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;$ &lt;/span&gt;bundle gem super
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gemspec configurations
&lt;/h2&gt;

&lt;p&gt;With the default files created, we need to modify the gemspec configuration to register the extension and also add the rake-compiler gem to be able to compile it in development. The important modifications are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding the "ext" folder to &lt;code&gt;spec.files&lt;/code&gt;. The ext folder is where the native extensions files will live&lt;/li&gt;
&lt;li&gt;Adding the extconf.rb file path to &lt;code&gt;spec.extensions&lt;/code&gt;. We'll go through what this file is later. For now, just remember that it needs to be inside the path "ext/NAME_OF_EXTENSION/"&lt;/li&gt;
&lt;li&gt;Adding the rake-compiler as a development dependency
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# super.gemspec&lt;/span&gt;

&lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"../lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="vg"&gt;$LOAD_PATH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$LOAD_PATH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"super/version"&lt;/span&gt;

&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"{app,config,db,lib,ext}/**/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="s2"&gt;"MIT-LICENSE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="s2"&gt;"Rakefile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="s2"&gt;"README.md"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"ext/super/extconf.rb"&lt;/span&gt;

  &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_development_dependency&lt;/span&gt; &lt;span class="s2"&gt;"rake-compiler"&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding the compile task
&lt;/h2&gt;

&lt;p&gt;After adding the rake-compiler gem, The compile task needs to be made available for the application. This is done by adding the following in our &lt;code&gt;Rakefile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rakefile&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"rake/extensiontask"&lt;/span&gt;

&lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ExtensionTask&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;"super"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lib_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lib/super"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The extconf file
&lt;/h2&gt;

&lt;p&gt;The extconf.rb file contains the configurations to generate the makefile used to compile the extension. Customizing this file can be quite tricky, involving manipulating global variables, checking the current platform and including external libraries.&lt;/p&gt;

&lt;p&gt;It becomes increasingly complex if the extension is split across many C files instead of a single one, for instance. However, the default configuration for a single file is straight forward.&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;# ext/super/extconf.rb&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"mkmf"&lt;/span&gt;

&lt;span class="n"&gt;extension_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"super"&lt;/span&gt;
&lt;span class="n"&gt;dir_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extension_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;create_makefile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extension_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the C extension
&lt;/h2&gt;

&lt;p&gt;This is certainly the most challenging part of building native extensions. Learning how to use all the functions and macros made available by the RubyVM takes time and a few gotchas might have you looking at your code with a confused expression on your face.&lt;/p&gt;

&lt;p&gt;An example of that is type conversions. A C float is not the same as a Ruby float and the appropriate macros need to be applied to handle values. If the input value is coming from Ruby into C, it needs to be converted into a C float. It must then be converted back to a Ruby float when returning to the Ruby context. Let's avoid type conversions in our super extension for simplicity.&lt;/p&gt;

&lt;p&gt;The two mandatory steps of the C extension are: including the RubyVM and creating an initializer for the extension (which is named Init_NAMEOFEXTENSION). Everything else is the gem's logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;# ext/super/super.c
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ruby.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Init_super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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;Let's dive into an example. We'll create the following class (represented here in pure Ruby) using the C extension.&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;# lib/super/super.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Super&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Super&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
      &lt;span class="vi"&gt;@var&lt;/span&gt; &lt;span class="o"&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;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The equivalent native extension would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;# ext/super/super.c
&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;SuperModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Qnil&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;SuperClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Qnil&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Init_super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="nf"&gt;super_initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Init_super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SuperModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_define_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Super"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;SuperClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_define_class_under&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SuperModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Super"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb_cObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;rb_define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SuperClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"initialize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;super_initialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="nf"&gt;super_initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rb_iv_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"@var"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb_hash_new&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The class Super is now defined with the initialize method as presented in pure Ruby. The functions and macros details are listed below.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;VALUE&lt;/em&gt; a macro for representing generic values&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Qnil&lt;/em&gt; Ruby's nil definition&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rb_define_module&lt;/em&gt; defines a module&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rb_define_class_under&lt;/em&gt; creates a class under a given module. The arguments are the module object, the class name as a string and the class it will inherit from (which is Object in this case)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rb_define_method&lt;/em&gt; defines the initialize method. The arguments are the class object where the method will be defined, the method name as a string, the method implementation function and the number of arguments&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rb_iv_set&lt;/em&gt; sets an instance variable to a given value. Takes the self object, the variable name, and the variable value&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rb_hash_new&lt;/em&gt; instantiates a new hash. Just like &lt;code&gt;{}&lt;/code&gt; in Ruby&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Knowing the available RubyVM functions and macros is essential for creating extensions, but they are undoubtedly hard to memorize. Documentation and examples provide valuable assistance during the process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.ruby-lang.org/en/2.4.0/extension_rdoc.html"&gt;Official docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://silverhammermba.github.io/emberb/c/"&gt;The Ruby C API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/andremedeiros/ruby-c-cheat-sheet"&gt;Ruby C cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Requiring the shared object
&lt;/h2&gt;

&lt;p&gt;The native extension has been written. We can now cross our fingers, compile it and require the resulting shared object. Compilation in development is done using the task we previously imported.&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;$ &lt;/span&gt;rake compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is the shared object file super.so under the lib folder. Requiring it in the gem's module will make all our definitions available.&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;# lib/super.rb&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"super/version"&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"super.so"&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing the extension
&lt;/h2&gt;

&lt;p&gt;Our extension is complete and tests can be written to verify it. By requiring the shared object file, everything defined in the C is now available as Ruby. Therefore, extensions are tested likewise regular Ruby code.&lt;/p&gt;

&lt;p&gt;Here is a possible test for the initialize method using rspec.&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;# spec/super/super_spec.rb&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"spec_helper"&lt;/span&gt;

&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Super&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Super&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :lib&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;".initialize"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;described_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"sets var as an empty hash"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Using pure Ruby or C native extensions is a tradeoff. Despite the significant performance advantage, C extensions increase the complexity of reading and writing code when compared to Ruby.&lt;/p&gt;

&lt;p&gt;Committing to using native extensions must be a conscious decision and the responsible team has to agree that the extra maintenance efforts will not surpass the performance benefits.&lt;/p&gt;

&lt;p&gt;Nonetheless, knowing your way around native extensions is yet another useful skill for the Rubyist toolbelt.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>c</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Customizing Rails rake tasks</title>
      <dc:creator>Vinicius Stock</dc:creator>
      <pubDate>Thu, 29 Nov 2018 21:43:03 +0000</pubDate>
      <link>https://dev.to/vinistock/customizing-rails-rake-tasks-3bg5</link>
      <guid>https://dev.to/vinistock/customizing-rails-rake-tasks-3bg5</guid>
      <description>&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;Rails rake tasks are commands that automate specific actions to be used either by the developers or by other mechanisms (e.g.: a deploy that will invoke rake tasks). Many tasks come configured with Rails out of the box to provide important functionality. In this post, I will explain how to override tasks and change their steps to customize them for your own application.&lt;/p&gt;

&lt;p&gt;Here are a few examples of out of the box tasks:&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;$ &lt;/span&gt;rake &lt;span class="nt"&gt;-T&lt;/span&gt;      &lt;span class="c"&gt;# Lists all rake tasks for the application&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rake         &lt;span class="c"&gt;# Default rake task. On a fresh application, does the same as rake test&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rake &lt;span class="nb"&gt;test&lt;/span&gt;    &lt;span class="c"&gt;# Task to run your tests (replaced by "rake spec" if using rspec instead of minitest)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rake db:seed &lt;span class="c"&gt;# Populates the database using the seeds.rb file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, tasks can quite easily be overridden to execute different actions. This is useful for defining steps for a build process that might include more than running the test suite or simply for changing the behavior of an existing task.&lt;/p&gt;

&lt;p&gt;Customizing rake tasks to fit your needs can improve your productivity and help to guarantee that everyone in the project is using a standardized process (or at least that they have the tools to easily do so).&lt;/p&gt;

&lt;h1&gt;
  
  
  How to do it?
&lt;/h1&gt;

&lt;p&gt;Overriding rake tasks is pretty straight forward. It involves two things: clearing the original task and re-defining it. Any code can go inside the new definition, however I recommend to neatly organize each step with their own rake task for simplicity.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to create a new rake task
&lt;/h3&gt;

&lt;p&gt;User defined rake tasks live inside the lib/tasks folder. Any file ending in ".rake" will be automatically picked up and loaded by Rails.&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;# lib/tasks/my_task.rake&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:custom&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"This take does something useful!"&lt;/span&gt;

  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:do_it&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;"Do something useful!"&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;Done! You can now invoke your new rake task using the command below. In the next section, we will go through on how to invoke it from other tasks.&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;$ &lt;/span&gt;rake custom:do_it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to override an existing task
&lt;/h3&gt;

&lt;p&gt;To override a task, clear the current behavior and re-define it in Rakefile. The example below will override the default rake to invoke our custom task.&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;# Rakefile&lt;/span&gt;
&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"config/application"&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;load_tasks&lt;/span&gt;
&lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;

&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"custom:do_it"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it! The default rake task can be configured to do whatever your application needs.&lt;/p&gt;

&lt;p&gt;In the next section, I will go through my usual set up for Rails applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  My preferred configuration
&lt;/h1&gt;

&lt;p&gt;The configuration I like to use overrides both the default and the test rake tasks, integrating them with a few tools. The steps for each are described below (check individual tool set up and configuration in their respective repos).&lt;/p&gt;

&lt;p&gt;If any of these steps break, build process is stopped and fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Steps run in the following order&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/presidentbeef/brakeman" rel="noopener noreferrer"&gt;Brakeman&lt;/a&gt; - Code analysis for security&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/grosser/parallel_tests" rel="noopener noreferrer"&gt;Parallel tests&lt;/a&gt; - Runs tests in parallel&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/rubocop-hq/rubocop" rel="noopener noreferrer"&gt;Rubocop&lt;/a&gt; - Code quality analysis&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/flyerhzm/rails_best_practices" rel="noopener noreferrer"&gt;Rails best practices&lt;/a&gt; - Best practices for Rails analysis&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/troessner/reek" rel="noopener noreferrer"&gt;Reek&lt;/a&gt; - Code smells analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Test&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one simply replaces running tests to use parallel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/grosser/parallel_tests" rel="noopener noreferrer"&gt;Parallel tests&lt;/a&gt; - Runs tests in parallel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we went through the high level description, let's get to business. Here is the Rakefile with the overridden tasks and the individual task definitions themselves.&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;# Rakefile&lt;/span&gt;
&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"config/application"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"rubocop/rake_task"&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;load_tasks&lt;/span&gt;
&lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;
&lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;

&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"brakeman:check"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"parallel:test"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;

  &lt;span class="no"&gt;RuboCop&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RakeTask&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="ss"&gt;:rubocop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"rubocop"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"rails_best_practices:run"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"reek:run"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
&lt;span class="k"&gt;end&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="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"parallel:test"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brakeman rake task&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;# lib/tasks/brakeman.rake&lt;/span&gt;
&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:brakeman&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Check your code with Brakeman"&lt;/span&gt;

  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:check&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"brakeman"&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Brakeman&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="ss"&gt;app_path: &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;print_report: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;pager: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="no"&gt;Brakeman&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Warnings_Found_Exit_Code&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filtered_warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rails best practices rake task&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;# lib/tasks/rails_best_practices.rake&lt;/span&gt;
&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:rails_best_practices&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Run rails best practices"&lt;/span&gt;

  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:run&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;"Running rails best practices!"&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="sb"&gt;`rails_best_practices`&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reek rake task&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;# lib/tasks/reek.rake&lt;/span&gt;
&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:reek&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Run reek"&lt;/span&gt;

  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:run&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;"Running reek!"&lt;/span&gt;
    &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"reek ."&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Gemfile&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;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:development&lt;/span&gt;&lt;span class="p"&gt;,&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;gem&lt;/span&gt; &lt;span class="s2"&gt;"brakeman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"parallel_tests"&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"rails_best_practices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"reek"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"rubocop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Overridden rake tasks can boost productivity and help enforce good practices among members of a team. Take advantage of them!&lt;/p&gt;

&lt;p&gt;What other tools would you integrate with rake tasks?&lt;/p&gt;

&lt;p&gt;What other uses can this capability have?&lt;/p&gt;

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