<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://mattsears.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://mattsears.com/" rel="alternate" type="text/html" /><updated>2025-09-16T17:35:13+00:00</updated><id>https://mattsears.com/feed.xml</id><title type="html">Matt Sears</title><subtitle>I mostly write about technology and business since that&apos;s been my livelyhood for the past twenty years, but I also write about my other interests including music, traveling, and other random topics.</subtitle><entry><title type="html">A Simple Technique to Improve Complex Methods</title><link href="https://mattsears.com/articles/2023/06/13/reduce-code-complexity-with-the-builder-pattern/" rel="alternate" type="text/html" title="A Simple Technique to Improve Complex Methods" /><published>2023-06-13T16:13:00+00:00</published><updated>2023-06-13T16:13:00+00:00</updated><id>https://mattsears.com/articles/2023/06/13/reduce-code-complexity-with-the-builder-pattern</id><content type="html" xml:base="https://mattsears.com/articles/2023/06/13/reduce-code-complexity-with-the-builder-pattern/"><![CDATA[<p>If you ever run <a href="https://github.com/seattlerb/flog">Flog</a> or
<a href="https://github.com/troessner/reek">Reek</a>, you’ve most likely encountered
<a href="https://github.com/troessner/reek/blob/master/docs/Too-Many-Statements.md">TooManyStatements</a> and
<a href="http://docs.seattlerb.org/flog/">VeryHighComplexity</a> violations in the results. I use Flog and Reek
continuously to help identify areas of improvement by flagging potential code smells, such as
excessive statements and high complexity early in the development cycle.<!--more--></p>

<p>In this post, I’ll show you a technique I use frequently when refactoring Ruby projects. Let’s
take a look at a method I ran across recently that had a very poor quality score.</p>

<h4 id="the-problem-method">The Problem Method</h4>

<p>This particular project is an e-commerce application that uses a rule engine-like way to perform
actions based on a set of rules defined by the store owner. The method below <em>returns a String
describing what the rule does in plain English</em>. I’ve shorten this example for brevity, but you can
clearly see it’s a mess.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/models/rule.rb</span>

<span class="k">def</span> <span class="nf">build_message</span>
  <span class="n">message</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"When"</span><span class="p">]</span>
  <span class="k">case</span> <span class="nb">self</span><span class="p">.</span><span class="nf">subject</span>
   <span class="k">when</span> <span class="s1">'shopping_cart'</span>
     <span class="k">if</span> <span class="n">target</span> <span class="o">==</span> <span class="s1">'sum'</span>
       <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"the Cart subtotal value"</span>
     <span class="k">elsif</span> <span class="n">target</span> <span class="o">==</span> <span class="s1">'count'</span>
       <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"the Cart items count"</span>
     <span class="k">end</span>
   <span class="k">when</span> <span class="s1">'inventory'</span>
     <span class="n">message</span> <span class="o">&lt;&lt;</span>  <span class="s2">"Stock level"</span>
   <span class="k">when</span> <span class="s1">'product'</span>
     <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"&lt;i&gt;</span><span class="si">#{</span><span class="n">product</span><span class="p">.</span><span class="nf">to_sentence</span><span class="si">}</span><span class="s2">&lt;/i&gt; page"</span>
   <span class="k">else</span>
     <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="n">values</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">', '</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">case</span> <span class="nb">self</span><span class="p">.</span><span class="nf">comparison</span>
   <span class="k">when</span> <span class="s1">'&gt;='</span>
     <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"is greater than"</span>
   <span class="k">when</span> <span class="s1">'&lt;='</span>
     <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"is less than"</span>
   <span class="k">else</span>
    <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"is equal to"</span>
  <span class="k">end</span>

  <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="n">values</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">','</span><span class="p">)</span>
  <span class="n">message</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
<span class="k">end</span>

<span class="n">rule</span><span class="p">.</span><span class="nf">build_message</span> <span class="c1">#=&gt; "When Cart value is greater than 10"</span>
</code></pre></div></div>

<p>When we want the rule in plain English, we call <code class="language-plaintext highlighter-rouge">rule.build_message</code> and get <em>“When Cart value is
greater than 10”</em>. After running Flog and Reek, we get two violations right away.</p>

<p>The “TooManyStatements” metric indicates when a method contains an excessive number of statements,
suggesting that it might be performing too many responsibilities. This can lead to increased
complexity, reduced readability, and difficulties in maintaining and testing the code.</p>

<p>The “VeryHighComplexity” issue highlighted by Reek points to methods with excessively high
cyclomatic complexity. Cyclomatic complexity measures the number of independent paths through a
method, indicating how difficult it is to understand, test, and maintain.</p>

<h4 id="the-solution-builder-pattern-by-another-name">The Solution: Builder Pattern (by another name)?</h4>

<p>To be honest, I don’t know if we can technically file this under any of the major <a href="https://en.wikipedia.org/wiki/Software_design_pattern">design
patterns</a>, but it’s similar to the <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder
Pattern</a> in which we’re creating a separate class for
building complex objects. In this case we’re building Strings, which are objects in Ruby so it kind of fits.</p>

<p>We’re going to create a new class for the purpose of constructing our message string. We’re
inheriting our new class from the Builder class which will contain shared helper methods we can take
advantage of.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/builders/rule_message.rb</span>

<span class="k">class</span> <span class="nc">Builders::RuleMessage</span> <span class="o">&lt;</span> <span class="no">Builder</span>
  <span class="nb">attr_accessor</span> <span class="ss">:rule</span>

  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">rule</span><span class="o">=</span><span class="n">rule</span><span class="p">)</span>
    <span class="vi">@rule</span> <span class="o">=</span> <span class="n">rule</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">message</span>
    <span class="n">message</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"When"</span><span class="p">]</span>
    <span class="n">build_subject</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">build_target</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">build_operators</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">build_variables</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">message</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">build_subject</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">build_shopping_cart</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">build_inventory</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">build_product</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">build_shopping_cart</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="k">return</span> <span class="k">unless</span> <span class="vi">@rule</span><span class="p">.</span><span class="nf">subject</span> <span class="o">==</span> <span class="s1">'shopping_cart'</span>
    <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"Cart"</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">build_inventory</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="k">return</span> <span class="k">unless</span> <span class="vi">@rule</span><span class="p">.</span><span class="nf">subject</span> <span class="o">==</span> <span class="s1">'inventory'</span>
    <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"Stock level"</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">build_product</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="k">return</span> <span class="k">unless</span> <span class="vi">@rule</span><span class="p">.</span><span class="nf">subject</span> <span class="o">==</span> <span class="s1">'product'</span>
    <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">"Product"</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">build_target</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="k">case</span> <span class="n">message</span><span class="p">.</span><span class="nf">target</span>
    <span class="k">when</span> <span class="s1">'sum'</span>
      <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s1">'subtotal value'</span>
    <span class="k">when</span> <span class="s1">'count'</span>
      <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s1">'item count'</span>
    <span class="k">end</span>
    <span class="n">message</span>
  <span class="k">end</span>

  <span class="c1"># Translates operators i.e. &gt;= to "Greater than or equal to"</span>
  <span class="k">def</span> <span class="nf">build_operators</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="n">translate_operator</span><span class="p">(</span><span class="n">message</span><span class="p">.</span><span class="nf">operator</span><span class="p">)</span> <span class="c1"># Helper method from parent Class</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">build_variables</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="vi">@rule</span><span class="p">.</span><span class="nf">values</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">' or '</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>As you can see, our Builder class is much more clean and straightforward. It defines an abstract
interface for creating the parts of the complex string e.g. message. It solves both
‘TooManyStatements’ and ‘VeryHighComplexity’ violation by:</p>

<ol>
  <li>
    <p>Separation of concerns: The Builder class separates the construction logic from the object’s
class, <code class="language-plaintext highlighter-rouge">Rule</code> in our case, allowing for greater flexibility and maintainability.</p>
  </li>
  <li>
    <p>Improved readability: The pattern makes the construction code more readable by encapsulating the
<strong>construction steps</strong> within our dedicated Builder class.</p>
  </li>
  <li>
    <p>Simplified message creation: Our Builder class provides a clear and structured way to create
complex strings with various scenarios, making the code more robust and easier to extend.</p>
  </li>
</ol>

<p>Let’s see our new Builder class in action:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Rule</span> <span class="o">&lt;</span> <span class="no">ApplicationModel</span>
  <span class="o">...</span>
  <span class="k">def</span> <span class="nf">to_s</span>
    <span class="no">Builders</span><span class="o">::</span><span class="no">RuleMessage</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">rule: </span><span class="nb">self</span><span class="p">).</span><span class="nf">message</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Here, we’re overriding the <code class="language-plaintext highlighter-rouge">to_s</code> method to display the String version of the Rule object. I don’t
always do this, but in this case I think it fits nicely since it is a String representation of the
Rule model.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rule</span> <span class="o">=</span> <span class="no">Rule</span><span class="p">.</span><span class="nf">active</span><span class="p">.</span><span class="nf">last</span>

<span class="n">rule</span><span class="p">.</span><span class="nf">to_s</span> <span class="c1">#=&gt;  "When Cart subtotal value is greater than 10"</span>
</code></pre></div></div>

<p>Overall, this technique simplifies construction of building strings in a step-by-step
manner while keeping the creation logic separate and providing flexibility. Whenever I encounter a
complex method that:</p>

<ol>
  <li>Has long lines of code.</li>
  <li>Uses a lot of <em>if / else</em> statements</li>
  <li>Is hard to follow or read</li>
</ol>

<p>I highly recommend employing this technique to streamline the code and enhance its quality. I have
extensively utilized this pattern over the years, and it proves immensely valuable when revisiting
the codebase after an extended period. By adopting this approach, it becomes significantly easier to
comprehend the code’s functionality and seamlessly incorporate enhancements for future
features. This practice fosters maintainability and ensures a smoother development experience in the
long run. Future Rubyists will thank you 😀.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[If you ever run Flog or Reek, you’ve most likely encountered TooManyStatements and VeryHighComplexity violations in the results. I use Flog and Reek continuously to help identify areas of improvement by flagging potential code smells, such as excessive statements and high complexity early in the development cycle.]]></summary></entry><entry><title type="html">Using SQL to improve your Ruby code</title><link href="https://mattsears.com/articles/2023/03/31/using-sql-to-improve-your-ruby-code/" rel="alternate" type="text/html" title="Using SQL to improve your Ruby code" /><published>2023-03-31T00:00:00+00:00</published><updated>2023-03-31T00:00:00+00:00</updated><id>https://mattsears.com/articles/2023/03/31/using-sql-to-improve-your-ruby-code</id><content type="html" xml:base="https://mattsears.com/articles/2023/03/31/using-sql-to-improve-your-ruby-code/"><![CDATA[<p>I love refactoring Ruby code. One of the best ways to clean Ruby code is by leaning more on your
database for the work. You not only make the Ruby code more efficient, we can spread the work load
between our web servers and database servers <!--more--> It may sound obvious, but I can’t count how
many times I’ve come across projects not utilizing the power of SQL.</p>

<p>Let’s take a look at an example I’ve recently came across. I’ve simplified the example for the
purposes of brevity, but the idea is the same. This particular project is using a dashboard view
displaying recent sales data and comparing results from previous months.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/dashboard_controller.rb</span>

<span class="k">def</span> <span class="nf">index</span>
  <span class="vi">@current_sales</span> <span class="o">=</span> <span class="no">Orders</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">created_at: </span><span class="no">DateTime</span><span class="p">.</span><span class="nf">now</span><span class="p">.</span><span class="nf">all_month</span><span class="p">)</span>
                         <span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="s1">'SUM(total) as total_sales'</span><span class="p">)</span>

  <span class="vi">@previous_sales</span> <span class="o">=</span> <span class="no">Orders</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">created_at: </span><span class="no">DateTime</span><span class="p">.</span><span class="nf">now</span><span class="p">.</span><span class="nf">last_month</span><span class="p">)</span>
                          <span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="s1">'SUM(total) as total_sales'</span><span class="p">)</span>
  <span class="o">...</span>
<span class="k">end</span>
</code></pre></div></div>

<p>In our controller, we’re retrieving the sales data from the current month and last month. It’s
pretty simple, but note we’re making two database queries to get the data we need. Now, let’s take a look at
the view:</p>

<div class="language-erb highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;table&gt;</span>
  <span class="nt">&lt;thead&gt;</span>
    <span class="nt">&lt;tr&gt;</span>
      <span class="nt">&lt;th&gt;</span>This Month's Sales<span class="nt">&lt;/th&gt;</span>
      <span class="nt">&lt;th&gt;</span>Last Month's Sales<span class="nt">&lt;/th&gt;</span>
      <span class="nt">&lt;th&gt;</span>Difference<span class="nt">&lt;/th&gt;</span>
    <span class="nt">&lt;/tr&gt;</span>
  <span class="nt">&lt;/thead&gt;</span>
  <span class="nt">&lt;tbody&gt;</span>
    <span class="nt">&lt;tr&gt;</span>
      <span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="vi">@current_sales</span><span class="p">.</span><span class="nf">total_sales</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
      <span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="vi">@previous_sales</span><span class="p">.</span><span class="nf">total_sales</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
      <span class="nt">&lt;td&gt;</span>
        <span class="cp">&lt;%=</span> <span class="n">number_to_percentage</span><span class="p">(</span>
          <span class="p">((</span><span class="vi">@current_sales</span><span class="p">.</span><span class="nf">total_sales</span> <span class="o">-</span> <span class="vi">@previous_sales</span><span class="p">.</span><span class="nf">total_sales</span><span class="p">)</span> <span class="o">/</span> <span class="vi">@current_sales</span><span class="p">.</span><span class="nf">total_sales</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span> <span class="cp">%&gt;</span>
        )%&gt;
      <span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;/tr&gt;</span>
  <span class="nt">&lt;/tbody&gt;</span>
<span class="nt">&lt;/table&gt;</span>
</code></pre></div></div>

<p>Okay merge the pull request because we’re done, right? <em>Wrong</em>. Although the above code solves the
business problem, we’ve created a few more problems down the road:</p>

<h4 id="the-problem">The Problem</h4>

<ol>
  <li><strong>It’s slow</strong>. As mentioned before, we have to make two queries to the database just for this
calculation and we’re using Ruby to do math which is slow.</li>
  <li><strong>It’s not reusable</strong>. If we want sales data somewhere else, we’ll have to write new code.</li>
  <li><strong>It’s limiting</strong>. We only have this month and last month’s data, but we know someone in the future is
going want to see more.</li>
</ol>

<h4 id="sql-lag-function-to-the-rescue">SQL LAG function to the Rescue</h4>

<p>Most popular databases have the <code class="language-plaintext highlighter-rouge">LAG()</code> function which gives us the ability look at the previous row
for comparing data to the current row. This is perfect since we need to see previous month’s sales
data to be able to calculate a percentage increase or decrease.</p>

<p>Let’s write our SQL code, but first, we’re going to wrap our SQL query into a plain Ruby object so
that it’s easier to test and re-use. In some cases, I like to organize SQL queries into it’s own
directory like <code class="language-plaintext highlighter-rouge">/app/queries</code>.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">#</span> <span class="n">app</span><span class="o">/</span><span class="n">queries</span><span class="o">/</span><span class="n">sales_data_query</span><span class="p">.</span><span class="n">rb</span>

<span class="k">class</span> <span class="n">SalesDataQuery</span>
  <span class="n">def</span> <span class="k">self</span><span class="p">.</span><span class="n">monthly_sales_report</span>
    <span class="n">sql_string</span> <span class="o">=</span> <span class="o">%</span><span class="n">Q</span><span class="p">{</span>
      <span class="k">WITH</span> <span class="n">sales</span> <span class="k">AS</span> <span class="p">(</span>
        <span class="k">SELECT</span>
          <span class="n">date_trunc</span><span class="p">(</span><span class="s1">'month'</span><span class="p">,</span> <span class="n">created_at</span><span class="p">)::</span><span class="nb">date</span> <span class="k">AS</span> <span class="n">order_month</span><span class="p">,</span>
          <span class="k">SUM</span><span class="p">(</span><span class="k">order</span><span class="p">.</span><span class="n">total</span><span class="p">)</span> <span class="k">AS</span> <span class="n">total_sales</span><span class="p">,</span>
        <span class="k">FROM</span> <span class="n">orders</span>
        <span class="k">GROUP</span> <span class="k">BY</span> <span class="n">date_trunc</span><span class="p">(</span><span class="s1">'month'</span><span class="p">,</span> <span class="n">created_at</span><span class="p">)</span>
      <span class="p">),</span>
      <span class="n">sales2</span> <span class="k">AS</span> <span class="p">(</span>
        <span class="n">order_month</span><span class="p">,</span>
        <span class="n">total_sales</span><span class="p">,</span>
        <span class="k">SELECT</span> <span class="n">LAG</span><span class="p">(</span><span class="n">total_sales</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="n">OVER</span> <span class="p">(</span><span class="k">ORDER</span> <span class="k">BY</span> <span class="nv">"created_at"</span><span class="p">)</span> <span class="n">previous_total_sales</span>
        <span class="k">FROM</span> <span class="n">sales</span>
      <span class="p">)</span>
      <span class="k">SELECT</span>
        <span class="n">order_month</span><span class="p">,</span>
        <span class="n">total_sales</span><span class="p">,</span>
        <span class="n">previous_total_sales</span><span class="p">,</span>
        <span class="p">(</span><span class="mi">100</span><span class="p">.</span><span class="mi">0</span><span class="o">*</span><span class="p">(</span><span class="n">total_sales</span> <span class="o">-</span> <span class="n">previous_total_sales</span><span class="p">)</span> <span class="o">/</span> <span class="k">NULLIF</span><span class="p">(</span><span class="n">total_sales</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span> <span class="n">percent_diff</span>
      <span class="k">FROM</span> <span class="n">sales2</span>
      <span class="k">ORDER</span> <span class="k">BY</span> <span class="nv">"created_at"</span> <span class="k">DESC</span>
    <span class="p">}</span>

    <span class="n">ActiveRecord</span><span class="p">::</span><span class="n">Base</span><span class="p">.</span><span class="k">connection</span><span class="p">.</span><span class="n">exec_query</span><span class="p">(</span><span class="n">sql_string</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>The SQL looks a little complicated, but it’s doing a lot of work for us. It’s adding up total sales
for this month and the previous months, plus it’s calculating the percent difference - all in one
SQL statement. The results look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>order_month | total_sales | previous_total_sales | percent_diff
------------+-------------+----------------------+-------------
          1 |        2000 | 1099                 | 45.05
          2 |        1001 | 2200                 | -119.78
          3 |        3400 | 3000                 | 11.76
          4 |        9909 | 8920                 | 9.98
...
</code></pre></div></div>

<p>As you can see, we not only have this month and last, we have all the months in the database. Let’s
go back to our code. In our controller, we make only one call to the database and we can loop
through the results in our view with no math calculations this time.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/dashboard_controller.rb</span>

<span class="k">def</span> <span class="nf">index</span>
  <span class="vi">@sales</span> <span class="o">=</span>  <span class="no">SalesDataQuery</span><span class="p">.</span><span class="nf">monthly_sales_report</span>
<span class="k">end</span>
</code></pre></div></div>

<div class="language-erb highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;table&gt;</span>
  <span class="nt">&lt;thead&gt;</span>
    <span class="nt">&lt;tr&gt;</span>
      <span class="nt">&lt;th&gt;</span>Month<span class="nt">&lt;/th&gt;</span>
      <span class="nt">&lt;th&gt;</span>Sales<span class="nt">&lt;/th&gt;</span>
      <span class="nt">&lt;th&gt;</span>% Difference<span class="nt">&lt;/th&gt;</span>
    <span class="nt">&lt;/tr&gt;</span>
  <span class="nt">&lt;/thead&gt;</span>
  <span class="nt">&lt;tbody&gt;</span>
    <span class="cp">&lt;%</span> <span class="vi">@sales</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">sale</span><span class="o">|</span> <span class="cp">%&gt;</span>
      <span class="nt">&lt;tr&gt;</span>
        <span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="n">sales</span><span class="p">.</span><span class="nf">month</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
        <span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="n">sales</span><span class="p">.</span><span class="nf">total_sales</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
        <span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="n">number_to_percentage</span><span class="p">(</span><span class="n">sale</span><span class="p">.</span><span class="nf">percent_diff</span><span class="p">)</span><span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
      <span class="nt">&lt;/tr&gt;</span>
    <span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span>
  <span class="nt">&lt;/tbody&gt;</span>
<span class="nt">&lt;/table&gt;</span>
</code></pre></div></div>

<p>Now this is a pull request we can approve!</p>

<p>This is just one example, but hopefully illustrates the point that knowing more about how utilizing
SQL queries can simplify your Ruby code and make your application run more efficiently. I encourage
you to take a closer look at the SQL language for your database of choice - there is a wealth of
power yet to be realized.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I love refactoring Ruby code. One of the best ways to clean Ruby code is by leaning more on your database for the work. You not only make the Ruby code more efficient, we can spread the work load between our web servers and database servers]]></summary></entry><entry><title type="html">Happy 30th Birthday Ruby</title><link href="https://mattsears.com/articles/2023/02/28/happy-birthday-ruby/" rel="alternate" type="text/html" title="Happy 30th Birthday Ruby" /><published>2023-02-28T20:52:00+00:00</published><updated>2023-02-28T20:52:00+00:00</updated><id>https://mattsears.com/articles/2023/02/28/happy-birthday-ruby</id><content type="html" xml:base="https://mattsears.com/articles/2023/02/28/happy-birthday-ruby/"><![CDATA[<p>Big happy birthday to Ruby! Ruby turned 30 this month so I thought I would share a little bit about
how I first discovered Ruby and why I still love it today. I was in high school when Ruby was
conceived, but it wouldn’t be another thirteen years before we would meet. <!--more--></p>

<p>Before Ruby, I was a Java programmer at a big tech company and before that I was a Perl programmer
at a book publishing company. I always enjoyed the process of building software and at that time I
was exploring all kinds of languages and tools. At the big tech company, the standard language was
Java so that was the main language at the time. They sent me to a software conference in San
Francisco in 2005 (I think), where I was eager to learn more about software design patterns, agile
development, continuous integration, and all that came along with the enterprise world. One evening,
they held an award ceremony called The Jolt Awards.</p>

<p>The Jolt awards awarded software creators in a variety of categories. One in particular was called
“Best New Framework” or “Best Web Framework”, I can’t remember which. I sat in the audience where
this young kid took the award for “Ruby on Rails”. This kid was approximately the same age as me,
dressed like me, and didn’t look anything like the other award winners which were mostly older,
not-so-well-dressed nerdy men. Needless to say, I was intrigued.</p>

<p>That night in the hotel, I installed Ruby on my laptop and was fascinate how easy it was to pick up
an run simple commands. It was like my old Perl days, but with objects and easier to
read. Eventually, I would get good enough and discover “the flow” and the utter joy of writing
code. It allowed me to shift from primarily focusing on the mechanics of the language (Java at the
time) to the actual features of the product - essentially going from “how” to “what”. Then, later
learning more about the community behind Ruby and interesting characters and books like “why’s
(poignant) Guide to Ruby” was icing on the cake.</p>

<p>It was more than just the language that spoke to me, it was the culture.  It was a profound shift. A
year or so later, I quit my big tech job and started my own consulting firm so I could write Ruby
everyday. And for fourteen years, I did just that - building hundreds of applications with Ruby and
getting paid for it. It has been one of the greatest endeavors of my life.</p>

<p>Today, I love Ruby as much today as I did seventeen years ago. Even though I’ve moved on from the
consulting world, I still write Ruby almost everyday in some way shape or form. And I don’t see
that changing anytime soon.</p>

<p>Thank you Ruby ❤️</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Big happy birthday to Ruby! Ruby turned 30 this month so I thought I would share a little bit about how I first discovered Ruby and why I still love it today. I was in high school when Ruby was conceived, but it wouldn’t be another thirteen years before we would meet.]]></summary></entry><entry><title type="html">Defensive Development</title><link href="https://mattsears.com/articles/2023/01/31/defensive-software/" rel="alternate" type="text/html" title="Defensive Development" /><published>2023-01-31T17:08:00+00:00</published><updated>2023-01-31T17:08:00+00:00</updated><id>https://mattsears.com/articles/2023/01/31/defensive-software</id><content type="html" xml:base="https://mattsears.com/articles/2023/01/31/defensive-software/"><![CDATA[<p>Much like <a href="https://en.wikipedia.org/wiki/Defensive_driving">Defensive Driving</a>, in which Wikipedia
describes “anticipating dangerous situations, despite adverse conditions or the mistakes of others
when operating a motor vehicle”, defensive development is building software that anticipates future
“one-off” features and deployments by having tools to solve problems already in production. <!--more--></p>

<p><img src="/assets/images/fullsize/chess-match.jpg" alt="Chess match" /></p>

<p>When I was a technical leader at a big tech company, releasing software to production was a big deal
involving many people and procedures - taking days sometimes weeks. It was particularly important to
have all the i’s dotted and t’s crossed, otherwise it may take another week to deploy another
release. In some cases, a small bug would slip through or even something smaller like a word
misspelled that would have to wait until the following week or petition for an emergency release.</p>

<p>Another common scenario is an outside department in the company needs a special “view” to the
application so that they can gain access to the software for their own purposes. They typically
would request our team to build a separate section just for them tying up our resources just to
build this special feature instead of focusing on our own customer needs. Does this sound
familiar?</p>

<p>Over many years of taking feature requests working with customers and external teams, you begin to
realize a common set of requests users always ask for post-production. In this post, I want to share
with you what I typically like to include with every piece of software I ship in order to anticipate
future requests and reduce the need to deploy special releases.</p>

<h4 id="1-administration-tool">1. Administration Tool</h4>

<p>By far the best and obvious way to make updates in production without re-deploying code is having an
administration tool in place. This can be for development team eyes only or even allow customers to
make updates as well. In Ruby On Rails applications, there are already a few great plugins that
makes it very easy. Here’s just a few examples that have helped my team:</p>

<ul>
  <li>Updating production database records like user information.</li>
  <li>Revoking user accounts or permissions.</li>
  <li>Removing fake or test account data.</li>
  <li>Changing the price of subscription plans.</li>
</ul>

<h4 id="2-a-private-api">2. A Private API</h4>

<p>Building an API in the software can be pretty simple to include. Again, for Ruby on Rails apps,
there are gems that make this simple. Having just a simple API in place and pay big dividends down
the road. When asked to get a special “access” in a lot of cases, you can just provide the API
endpoints and connection details and they can build their own application themselves.</p>

<h4 id="3-managed-tool-for-error-logging">3. Managed Tool for Error Logging</h4>

<p>If I had a nickel for every time I got an email saying “the website was down last night” and then
spending hours trying to figure out what happened, well, I’d have a lot of nickels. Having a way to
search log files is a crucial way to track down issues or even false alarms. A lot of the time it’s
the hosting provider having network issues. Tools like <a href="https://www.datadoghq.com">DataDog</a> gives
you the ability to track down errors and when they occur. If anything, it’s been a great way to
point out there weren’t any issues at all and we can move on to the next task.</p>

<h4 id="4-healthcheck-aka-smoketest-page">4. Healthcheck (aka Smoketest) Page</h4>

<p>This is one of the oldest and my personal favorite trick. Often times I will build a page in the application
that only I can get to (i.e. /smoketest) that will give me a basic vitals of the system. For
example:</p>

<ul>
  <li>First and foremost, make sure the application is still running.</li>
  <li>Show the number of active users to make sure the application is database connection is fine.</li>
  <li>Display the status of connection to third-party api’s to check the connection is working.</li>
</ul>

<p>When getting that dreaded email saying “something’s wrong with the site”, I’ll check the smoketest
page first to make sure all is working or quickly determine the issue.</p>

<h4 id="5-routine-maintenance-task-page">5. Routine Maintenance Task Page</h4>

<p>Similar to the administration tool, having a section in the application where the development team
can queue routine maintenance tasks i.e. Rake tasks, is a great time saver. The folks at
Shopify have a gem for this called <a href="https://github.com/Shopify/maintenance_tasks">Maintenance Tasks</a>
that works great. Here are some examples of maintenance tasks I’ve used in production before:</p>

<ul>
  <li>Deleting inactive user records to clean up the database.</li>
  <li>Clearing production cache assets to make sure all cached assets are up-to-date.</li>
  <li>Re-running scheduled tasks in case there was an outage from the night before.</li>
</ul>

<p>After your the application has been in production a while and you’ve implemented tools like listed
above, you’ll notice fewer and fewer emergency releases and having more to time focus on adding
value your customers will love.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Much like Defensive Driving, in which Wikipedia describes “anticipating dangerous situations, despite adverse conditions or the mistakes of others when operating a motor vehicle”, defensive development is building software that anticipates future “one-off” features and deployments by having tools to solve problems already in production.]]></summary></entry><entry><title type="html">Wanderment</title><link href="https://mattsears.com/articles/2022/12/30/wanderment/" rel="alternate" type="text/html" title="Wanderment" /><published>2022-12-30T18:22:00+00:00</published><updated>2022-12-30T18:22:00+00:00</updated><id>https://mattsears.com/articles/2022/12/30/wanderment</id><content type="html" xml:base="https://mattsears.com/articles/2022/12/30/wanderment/"><![CDATA[<p>I’ve always been a walker as for as I can remember. By “walker”, I don’t mean just hiking, but
rather just walk-out-the door walker. I walked to school, I walk to work, I walk
to get coffee, I walk anywhere and everywhere I can. I make it a point to walk the streets because
for me to feel grounded, it requires my feet on the ground. <!--more--></p>

<p>Since having issues with my <a href="/articles/2021/08/30/taking-care-of-your-vision">eyesight</a> last year,
walking has turned into something more. Walking as a pastime, walking without aim, walking with no
destination. A state of no path to find a path, it’s what I call  <em>wanderment</em>.</p>

<p><img src="/assets/images/fullsize/wanderment-one.jpeg" alt="Wanderment one" /></p>

<p>I’ve walked more in the past year than I have ever walked before in my life. Since being forced to
severely reduce my screen time, I’ve gone back back outside and it has made me see earth and life in
a different way (ironically). I just so happen to live in a beautiful part of the country with
mountains, beaches, and city buildings, all within a few miles, so it was only natural that I walk
every square inch.</p>

<p><img src="/assets/images/fullsize/wanderment-two.jpeg" alt="Wanderment two" /></p>

<p>Wanderment has become a large part of my therapy. Along the way, I’ve discovered some amazing
benefits. Not just obvious physical benefits, but a substantial increase in levels of
emotional and spiritual energy too. Here are just a few:</p>

<p><strong>Reduces anxiety</strong>. Reductions in anxiety are subtle, but noticeable. During difficult times, just
getting outside and walking for a few blocks (aimlessly) improves my mood and it’s my go-to way to
feel better.</p>

<p><strong>Clears out the cobwebs in the brain</strong>. I’ve noticed a increased level of function in my
brain. Walking aimlessly without a goal, mission, or purpose, allows my brain to think about other
things. Things I’ve not had time or energy to think about before.</p>

<p><img src="/assets/images/fullsize/wanderment-three.jpeg" alt="Wanderment three" /></p>

<p><strong>Creativity boost</strong>. Related to cleaning out the cobwebs in the ol’ brain, having some extra space
in the brain leaves room for creative ideas to naturally sneak in. Through many walks, I’ve
come up with ideas, solved long-standing problems, and lofty goals seem more attainable.</p>

<p><strong>Getting closer to calm</strong>. Most days, it’s completely chaos in my head. With all that’s happening in
  the world and the internal pressures relationships, career, family, etc., it can be all
  overwhelming. Wanderment, allows me to take a break from all that noise and re-center myself. I
  can focus on what’s really important in life.</p>

<p>We can go a little further. Here are a few activities I like to do that have greatly benefited me
and how I get the most out of wanderment. <em>Take time to listen to nature.</em> Find a nice place to take
break. Stop and just listen to what’s happening around you. Listen the birds, the leaves, the waves,
etc. <em>Feel the earth.</em> Sit on the ground, dig your feet into the sand, brush your hands on over the
grass. <em>Deep breaths.</em>  Smell the salty air, feel the wind in your face.</p>

<p>Getting lost in the world, as it seems, has set me on a path to finding myself. I haven’t arrived by
any means, but I feel like I’m in the right direction.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I’ve always been a walker as for as I can remember. By “walker”, I don’t mean just hiking, but rather just walk-out-the door walker. I walked to school, I walk to work, I walk to get coffee, I walk anywhere and everywhere I can. I make it a point to walk the streets because for me to feel grounded, it requires my feet on the ground.]]></summary></entry><entry><title type="html">Maintainable Rails: A Rails Engine Strategy</title><link href="https://mattsears.com/articles/2022/09/12/standardizing-your-stack-with-rails-engines/" rel="alternate" type="text/html" title="Maintainable Rails: A Rails Engine Strategy" /><published>2022-09-12T15:11:00+00:00</published><updated>2022-09-12T15:11:00+00:00</updated><id>https://mattsears.com/articles/2022/09/12/standardizing-your-stack-with-rails-engines</id><content type="html" xml:base="https://mattsears.com/articles/2022/09/12/standardizing-your-stack-with-rails-engines/"><![CDATA[<p>If you’ve ever worked for a company or organization that runs multiple Rails applications, you’ve
most likely seen these projects using different sets of plugins, front-end frameworks, coding
techniques, test frameworks, etc. etc. Ultimately having a ton of technical debt leading to
heavy context switching slowing progress to a crawl. Most of the time it’s inevitable
because keeping multiple applications up-to-date and consistent is a daunting task.<!--more--></p>

<p>I’ve seen this countless times in my career when running a consulting company and when I worked for
a big IT company. In this article, I want to share with you one technique I use to help <em>pay down
the technical debt and pave a path forward</em> to a more sound development team using <a href="https://guides.rubyonrails.org/engines.html">Rails Engines</a>.</p>

<h4 id="quick-intro-to-rails-engines">Quick intro to Rails Engines</h4>

<p>The term “engine” can be confusing because it’s not really anything different than what we’ve
already been working with. A Rails Engine is a Rails application with some special options that
allow us to “hook” into it. I think of it as a Rails module (like a Ruby module) that we’re adding
to our code, but instead of getting additional Ruby methods, we can a whole web application at our disposal.</p>

<p>This means we can pack a whole bunch of common/shared functionality into our engine including
models, controllers, views, and even assets like Javascript, CSS, and image assets.</p>

<p>Let’s kicks things off with an example engine. Let’s say our company wants to build an engine called <code class="language-plaintext highlighter-rouge">CompanyStack</code>:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>rails plugin new company_stack <span class="nt">--mountable</span>
</code></pre></div></div>

<p>We’re going to isolate our engine so that we can namespace our ruby code to avoid any collisions in
naming. This will help our engine be independent from any application that uses it. It’s important
to think of our engine as completely separate from any application that uses it. Combined with the
<code class="language-plaintext highlighter-rouge">--mountable</code> option (above), using the <code class="language-plaintext highlighter-rouge">isolate_namespace</code> will provide independence we need:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># lib/company_stack/engine.rb</span>

<span class="k">module</span> <span class="nn">CompanyStack</span>
  <span class="k">class</span> <span class="nc">Engine</span> <span class="o">&lt;</span> <span class="o">::</span><span class="no">Rails</span><span class="o">::</span><span class="no">Engine</span>
    <span class="n">isolate_namespace</span> <span class="no">CompanyStack</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Now we can include our engine in our Rails application’s Gemfile:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gem</span> <span class="s2">"company_stack"</span><span class="p">,</span> <span class="ss">path: </span><span class="s2">"../path/to/company_stack"</span>
</code></pre></div></div>

<p>Let’s say our company has a few Rails applications in production. Upper management is
complaining about the amount of time it takes to ship code. Some of our new engineers
aren’t as familiar with older versions of Rails so it’s more difficult to assign
team members to projects. Our senior engineers are complaining about the sheer amount of redundant
code across our projects. Our Devops team wants to upgrade our servers, but can’t because some
applications can’t run on newer versions of Ruby, SSL, Postgres, etc etc. Sound familiar?</p>

<p>What are our goals with making our development team more efficient?</p>

<ol>
  <li>Reduce the overall development churn so we can ship new features faster.</li>
  <li>Provide a clear direction on our company’s official technical stack.</li>
</ol>

<h4 id="using-rails-engines-to-define-our-organization-stack">Using Rails Engines to Define Our Organization Stack</h4>

<p>Do we know our company’s official technology stack? We hope that it’s Ruby, but what about
the gems and libraries we should be using? This is crucial in keeping our applications
consistent. How many times have we come across a project that uses Rspec and another one using
Minitest? It’s important to define what and how we should be writing our applications so
that we can keep our code consistent and reduce the context switching. A good place to start is the
<code class="language-plaintext highlighter-rouge">gemspec</code> file in our engine:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># /company_stack.gemspec</span>

<span class="no">Gem</span><span class="o">::</span><span class="no">Specification</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span> <span class="o">|</span><span class="n">spec</span><span class="o">|</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'rails'</span><span class="p">,</span> <span class="s1">'&gt;= 7.0.3.1'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'turbo-rails'</span><span class="p">,</span> <span class="s1">'~&gt; 1.0.1'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'hotwire-rails'</span><span class="p">,</span> <span class="s1">'~&gt; 0.1.3'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'pg'</span><span class="p">,</span> <span class="s1">'&gt;= 1.3.5'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'view_component'</span><span class="p">,</span> <span class="s1">'~&gt; 2.53.0'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'redis'</span><span class="p">,</span> <span class="s1">'~&gt; 4.8'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'cssbundling-rails'</span><span class="p">,</span> <span class="s1">'~&gt; 1.1.1'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'jsbundling-rails'</span><span class="p">,</span> <span class="s1">'~&gt; 1.0.2'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'bcrypt'</span><span class="p">,</span> <span class="s1">'~&gt; 3.1.18'</span>
  <span class="n">spec</span><span class="p">.</span><span class="nf">add_dependency</span> <span class="s1">'puma, '</span><span class="o">~&gt;</span> <span class="mf">5.6</span><span class="err">'</span>
  <span class="o">...</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Here we are defining that Rails 7 with Hotwire, Postgres, Redis, and Puma as our official stack. We
can include additional gems like Mintest, Devise, Sidekiq - you name it. This is taken from my own
company’s official stack and it means all Rails applications that includes the <code class="language-plaintext highlighter-rouge">CompanyStack</code> engine
must be written with these tools - no Rspec, no Mysql, no fancy Javascript libraries unless
officially approved. If your company’s Rails applications are older, then it most likely makes sense
require lesser versions of Rails, say 6 and up until everything is caught up.</p>

<h4 id="central-place-for-shared-and-common-code">Central Place for Shared and Common Code</h4>

<p>Once we have our engine installed on our Rails applications, we can begin to explore ways to reduce
code redundancy. Of course, each application is unique, but there will always be cases of common
code. For example, most applications has a <code class="language-plaintext highlighter-rouge">User</code> model and that can be one area to extract common
functionality.</p>

<p>Here’s a simplified example: We’ve looked at a few of our Rails applications and we’ve noticed that
we’re authenticating the User in multiple ways. As an organization, it would be nice that all our
projects authenticate the same way so we know that our applications are secure and up-to-date. We’ll
create a Concern in our engine that authenticates a user using email and password.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># /app/models/concern/company_stack/users/auth</span>

<span class="k">module</span> <span class="nn">CompanyStack</span>
  <span class="k">module</span> <span class="nn">Users::Utils</span>
    <span class="kp">extend</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Concern</span>

    <span class="n">class_methods</span> <span class="k">do</span>
      <span class="k">def</span> <span class="nf">login</span><span class="p">(</span><span class="n">login</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
         <span class="o">...</span>
      <span class="k">end</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Now, all we have to do is include the Concern in our Rails application and we instantly have a way
to authenticate user records. Eventually, we can remove the old code from the application and just
use the engine to authenticate our users.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">User</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="kp">include</span> <span class="no">CompanyStack</span><span class="o">::</span><span class="no">Users</span><span class="o">::</span><span class="no">Authentication</span>
  <span class="kp">include</span> <span class="no">CompanyStack</span><span class="o">::</span><span class="no">Users</span><span class="o">::</span><span class="no">Utils</span>
  <span class="o">..</span>
<span class="k">end</span>

<span class="c1">#=&gt; current_user = User.login("mattsears", "******")</span>
</code></pre></div></div>

<p>This is a very simplified example, but hopefully it illustrates the potential in using Rails engines
as a way to cut down technical debt. The nice thing about using Concerns, is that our applications
aren’t required to use the new authentication until they’re ready i.e. including <code class="language-plaintext highlighter-rouge">include
CompanyStack::Users::Authentication</code> in our User model. The additional bonus is we don’t have to
rewrite the user authentication for any new applications we create.</p>

<p>We’re not just restricted to sharing Ruby code either, we can share assets like Javascript and
stylesheets as well. At my company, our official front-end stack is
<a href="https://hotwired.dev">Hotwired</a> and <a href="https://tailwindcss.com">TailwindCSS</a> and so we can include
these libraries in our engine’s asset pipeline.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// package.json (in CompanyStack)</span>

<span class="p">{</span>
  <span class="dl">"</span><span class="s2">dependencies</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
    <span class="dl">"</span><span class="s2">@hotwired/stimulus</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">3.0.1</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">@hotwired/turbo-rails</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^7.1.1</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">@rails/actioncable</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^6.1.5</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">@rails/activestorage</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^6.1.5</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">esbuild</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^0.15.6</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">postcss</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^8.4.6</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">postcss-flexbugs-fixes</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^5.0.2</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">postcss-import</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^14.0.2</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">postcss-nesting</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^10.1.2</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">postcss-preset-env</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^7.3.1</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">tailwindcss</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">^3.0.20</span><span class="dl">"</span>
  <span class="p">},</span>
  <span class="dl">"</span><span class="s2">scripts</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
    <span class="dl">"</span><span class="s2">build:css</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">tailwindcss --postcss -i ./app/assets/stylesheets/company_static/application.css -o ./app/assets/builds/company_stack/application.css</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">build</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">esbuild app/javascript/*.* --minify --bundle --outdir=app/assets/builds/company_stack</span><span class="dl">"</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Speaking of asset pipelines, we can also include custom stylesheets for example, that match our
company brand <em>and/or</em> we can also include Stimulus controllers that provide common Javascript
functions. Now, all we have to do is include the assets in our applications layouts:</p>

<div class="language-erb highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;head&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span> <span class="nt">/&gt;</span>
    <span class="c">&lt;!-- CompanyStack Engine's assets --&gt;</span>
    <span class="cp">&lt;%=</span> <span class="n">stylesheet_link_tag</span> <span class="s1">'company_stack/application'</span><span class="p">,</span> <span class="ss">media: </span><span class="s1">'all'</span> <span class="cp">%&gt;</span>
    <span class="cp">&lt;%=</span> <span class="n">javascript_include_tag</span> <span class="s1">'company_stack/application'</span>  <span class="cp">%&gt;</span>

    <span class="c">&lt;!-- This application's assets --&gt;</span>
    <span class="cp">&lt;%=</span> <span class="n">stylesheet_link_tag</span> <span class="s1">'application'</span><span class="p">,</span> <span class="ss">media: </span><span class="s1">'all'</span> <span class="cp">%&gt;</span>
    <span class="cp">&lt;%=</span> <span class="n">javascript_include_tag</span> <span class="s1">'application'</span>  <span class="cp">%&gt;</span>
    ...
</code></pre></div></div>

<p>And now our Rails application includes all of our company’s official front-end stack and is ready
to take advantage of all the code that has already been written - keeping our Rails applications not
only using less code, but looking consistent too.</p>

<p>We don’t have to stop here either, we can include application helpers, background workers, view
components, and more in our engine.</p>

<h4 id="in-review">In Review</h4>

<p>Hopefully I’ve illustrated the power as using with Rails Engines as an overall strategy to help your
organization get on the right track with more maintainable applications.  For my company, we’ve been
using this strategy for a while and it has paid a lot of dividends and I think it can help you’re
team too.</p>]]></content><author><name></name></author><category term="ruby" /><summary type="html"><![CDATA[If you’ve ever worked for a company or organization that runs multiple Rails applications, you’ve most likely seen these projects using different sets of plugins, front-end frameworks, coding techniques, test frameworks, etc. etc. Ultimately having a ton of technical debt leading to heavy context switching slowing progress to a crawl. Most of the time it’s inevitable because keeping multiple applications up-to-date and consistent is a daunting task.]]></summary></entry><entry><title type="html">The Joy of Side Projects</title><link href="https://mattsears.com/articles/2022/04/13/the-joy-of-side-projects/" rel="alternate" type="text/html" title="The Joy of Side Projects" /><published>2022-04-13T17:05:00+00:00</published><updated>2022-04-13T17:05:00+00:00</updated><id>https://mattsears.com/articles/2022/04/13/the-joy-of-side-projects</id><content type="html" xml:base="https://mattsears.com/articles/2022/04/13/the-joy-of-side-projects/"><![CDATA[<p>Have you ever got excited about an idea and wish you could do, but never have the time to start?
This has been my personal dilemma for as long as I can remember - that trapped feeling working on a
other people’s ideas to pay the bills while daydreaming about working on my own stuff. Over the past
few years, I’ve been working on few techniques to help break through this quandary.<!--more--></p>

<ol>
  <li>Pick a project that gives you the most energy.</li>
  <li>Only work on what will ship with version one.</li>
  <li>Run the project like you’re part of a team.</li>
  <li>Enjoy your work.</li>
</ol>

<h4 id="follow-your-energy">Follow Your Energy</h4>

<p>I’m at a certain age where I’ve been around the block a few times. New technology and tools don’t
excite me as much as they used to. No longer can I slug through a boring project with the energy
gained from learning a new programming language or framework. Don’t get me wrong, I
still enjoy learning new things, but I’ve learned to love mastering my current set of tools even
more. I can start a new project knowing exactly how it should be built - like a lumber jack and a
sharp axe, I know how to chop this tree down. This paired with a new brand new idea, I have all the
energy I need.</p>

<h4 id="bare-minimum-prototype">Bare Minimum Prototype</h4>

<p>Ideas have a way of spreading like wildfire. The key here is keeping a list of everything you want
your project to accomplish. Now cut that list to the bare minimum for the initial release and
that’s what you will work on first. The rest goes into the backlog. Whenever you get a new idea, put
it in the backlog so you don’t keep that idea in your head. Getting your first working prototype
deployed to production is the hardest part of any project. Having too many ideas stored in your
brain kills momentum and can cause you to second-guess decisions.</p>

<h4 id="project-management-for-one">Project Management for One</h4>

<p>Now that you have your tasks separated into a backlog, we can plan out our project. Even if I’m the
only one working on the project, I still use a fancy project management tool to keep track of
progress. I could easily work off some note cards or a spreadsheet, but I still queue my tasks in a
software tools build for teams. Tools like Github Project, Jira, or in my case, Asana which I’ve
used for years while running a consulting firm. Why you may ask? For starters, it feels more
familiar to me and it’s proven successful in previous projects, but most of all, it keeps me
accountable to myself. I assign a task to myself with a deadline, and this gives me a complete
roadmap. Asana sends me a few reminders when things are due and I can tick them off one-by-one. I
promise you, at the end of the week, you will feel proud seeing the list of complete tasks.</p>

<h4 id="its-not-a-race">It’s Not a Race</h4>

<p>Truly rewarding work is work you are proud of, not how fast you do it. As I always say, you will be
remembered for the work you put into this world, not that you got it done <em>on time</em>. Deadlines
come and go, but the work is what persists in time. So it’s okay that you missed that target date so
long as you are enjoying the process. That is the joy of side-projects after all. Make your side
projects fun and you will complete them every time.</p>]]></content><author><name></name></author><category term="misc" /><summary type="html"><![CDATA[Have you ever got excited about an idea and wish you could do, but never have the time to start? This has been my personal dilemma for as long as I can remember - that trapped feeling working on a other people’s ideas to pay the bills while daydreaming about working on my own stuff. Over the past few years, I’ve been working on few techniques to help break through this quandary.]]></summary></entry><entry><title type="html">Favorite Tools for Working in Ruby / Rails</title><link href="https://mattsears.com/articles/2022/02/28/favorite-tools-for-working-in-ruby-and-rails/" rel="alternate" type="text/html" title="Favorite Tools for Working in Ruby / Rails" /><published>2022-02-28T00:00:00+00:00</published><updated>2022-02-28T00:00:00+00:00</updated><id>https://mattsears.com/articles/2022/02/28/favorite-tools-for-working-in-ruby-and-rails</id><content type="html" xml:base="https://mattsears.com/articles/2022/02/28/favorite-tools-for-working-in-ruby-and-rails/"><![CDATA[<p>Over at the Shopify Enginneer Twitter account, an interesting question was posted that got me
thinking about my favorite and most used Ruby/Rails tools. It’s nice to see what other devs are
using so I thought I would share with you what I use the most on a daily basis. In a lot of cases,
I’ve been using the same tools for over a decade.<!--more--></p>

<center class="py-4">
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">What are your favorite tools for working in <a href="https://twitter.com/hashtag/Ruby?src=hash&amp;ref_src=twsrc%5Etfw">#Ruby</a> or <a href="https://twitter.com/rails?ref_src=twsrc%5Etfw">@Rails</a>?</p>&mdash; Shopify Engineering (@ShopifyEng) <a href="https://twitter.com/ShopifyEng/status/1493608793950896131?ref_src=twsrc%5Etfw">February 15, 2022</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>

<h3 id="1-emacs">1. Emacs</h3>

<p>Those who know me, could have guessed this one. I’ve been a Emacs users for over twenty years - ever
since starting out programming in Perl all those years ago. Since then, I’ve customized and
maintained my <a href="https://github.com/mattsears/emacs">configuration</a> for web development and more
specifically for Ruby / Rails development.</p>

<h3 id="2-tmux-with-tmuxinator">2. Tmux with Tmuxinator</h3>

<p>I live in the terminal all day long - writing, coding, notes and
more. <a href="https://github.com/tmuxinator/tmuxinator">Tmuxinator</a> is by far the most used Ruby gem in my
arsenal and helps me manages all my Tmux sessions with a simple YAML configuration file. Each Tmux
session is a project more-or-less and inside each session I have windows and panes usually dedicated
to a single task or context. Let’s take a look at an example, here is a Tmuxinator configuration for
a typical Ruby on Rails project:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="ss">name: </span><span class="k">super</span><span class="o">-</span><span class="n">duper</span><span class="o">-</span><span class="n">project</span>
<span class="ss">root: </span><span class="o">~</span><span class="sr">/Workspace/</span><span class="n">active</span><span class="o">/</span><span class="k">super</span><span class="o">-</span><span class="n">duper</span>
<span class="ss">windows:
  </span><span class="o">-</span> <span class="ss">editor: </span><span class="n">emacsclient</span> <span class="o">-</span><span class="n">t</span> <span class="no">README</span><span class="p">.</span><span class="nf">md</span>
  <span class="o">-</span> <span class="ss">shell: </span><span class="n">clear</span>
  <span class="o">-</span> <span class="ss">console: </span><span class="n">rails</span> <span class="n">c</span>
  <span class="o">-</span> <span class="ss">testing:
      layout: </span><span class="n">even</span><span class="o">-</span><span class="n">horizontal</span>
      <span class="ss">panes:
        </span><span class="o">-</span> <span class="n">emacsclient</span> <span class="o">-</span><span class="n">t</span> <span class="nb">test</span><span class="o">/</span><span class="n">test_helper</span><span class="p">.</span><span class="nf">rb</span>
        <span class="o">-</span> <span class="n">bundle</span> <span class="nb">exec</span> <span class="n">guard</span>
  <span class="o">-</span> <span class="ss">logs: </span><span class="n">tail</span> <span class="o">-</span><span class="n">f</span> <span class="n">log</span><span class="o">/</span><span class="n">development</span><span class="p">.</span><span class="nf">log</span>
  <span class="o">-</span> <span class="ss">workers: </span><span class="n">dev</span>
</code></pre></div></div>
<p>When I run <code class="language-plaintext highlighter-rouge">tmuxinator super-duper-project</code> in the terminal, Tmuxinator fires up Tmux and creates six windows in the
project directory:</p>

<ol>
  <li><em>editor</em>: Starts and Emacs session by opening up README.md file to get things started.</li>
  <li><em>shell</em>: Used for mostly running <code class="language-plaintext highlighter-rouge">rake</code> and <code class="language-plaintext highlighter-rouge">rails</code> commands.</li>
  <li><em>console</em>: Starts a Rails console session for code exploration.</li>
  <li><em>testing</em>: Starts an Emacs session in the test directory and splits the window with <code class="language-plaintext highlighter-rouge">guard</code> that
watches for changes in test files and runs tests automatically as I update the code.</li>
  <li>logs: Tails the development log so I can see requests and errors.</li>
  <li><em>workers:</em> Runs commands in the Procfile.dev file like the Rails server, yarn, and background workers.</li>
</ol>

<p>Here is another configuration for this very website. I use Jekyll for this blog and have three
windows setup. With command <code class="language-plaintext highlighter-rouge">tmuxinator website</code>, I can jump right into the project, run <code class="language-plaintext highlighter-rouge">bundle exec jekyll draft "My new draft"</code>, in the shell window, start the
Jekyll server, and start writing.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># ~/.tmuxinator/website.yml</span>

<span class="ss">name: </span><span class="n">website</span>
<span class="ss">root: </span><span class="o">~</span><span class="sr">/Workspace/</span><span class="n">active</span><span class="o">/</span><span class="n">website</span>
<span class="ss">windows:
  </span><span class="o">-</span> <span class="ss">editor: </span><span class="n">emacsclient</span> <span class="o">-</span><span class="n">t</span> <span class="no">README</span><span class="p">.</span><span class="nf">md</span>
  <span class="o">-</span> <span class="ss">shell:
  </span><span class="o">-</span> <span class="ss">server: </span><span class="n">bundle</span> <span class="nb">exec</span> <span class="n">jekyll</span> <span class="n">serve</span> <span class="o">--</span><span class="n">drafts</span> <span class="o">--</span><span class="n">livereload</span> <span class="o">--</span><span class="n">livereload_port</span> <span class="mi">8888</span>
</code></pre></div></div>

<h3 id="3-minitest">3. Minitest</h3>

<p>I’ve written many times about <a href="https://github.com/seattlerb/minitest">Minitest</a> and it’s been my
standard testing framework for a long, long time. It’s strength is it’s simplicity, which results in
a simpler test suite. Having a simple and straightforward test suite is crucial for long-term
success. Here is an example of a simple, yet beautiful test:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># frozen_string_literal: true</span>

<span class="nb">require</span> <span class="s1">'test_helper'</span>

<span class="k">class</span> <span class="nc">DateTimeHelperTest</span> <span class="o">&lt;</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
  <span class="kp">include</span> <span class="no">DateTimeHelper</span>

  <span class="n">let</span><span class="p">(</span><span class="ss">:date_range</span><span class="p">)</span> <span class="p">{</span> <span class="kp">nil</span><span class="o">..</span><span class="kp">nil</span> <span class="p">}</span>

  <span class="n">subject</span> <span class="p">{</span> <span class="n">format_date_range</span><span class="p">(</span><span class="n">date_range</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">describe</span> <span class="s1">'with no range at all'</span> <span class="k">do</span>
    <span class="n">it</span> <span class="s1">'does not format date'</span> <span class="k">do</span>
      <span class="n">assert_equal</span> <span class="s1">'Anytime'</span><span class="p">,</span> <span class="n">subject</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="n">describe</span> <span class="s1">'with a date range on the same day'</span> <span class="k">do</span>
    <span class="n">let</span><span class="p">(</span><span class="ss">:date_range</span><span class="p">)</span> <span class="p">{</span> <span class="no">DateTime</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2022</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span><span class="o">..</span><span class="no">DateTime</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2022</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">9</span><span class="p">)</span> <span class="p">}</span>

    <span class="n">it</span> <span class="s1">'formats the date range on same day'</span> <span class="k">do</span>
      <span class="n">assert_equal</span> <span class="s1">'Oct 12, 2022 08:00am - 09:00am'</span><span class="p">,</span> <span class="n">subject</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<h3 id="4-guard">4. Guard</h3>

<p>As I mentioned in my Tmuxinator config above, I run
<a href="https://github.com/guard/guard">Guard</a> continuously in the background. Specifically, it watches for
any changes to the code and runs related tests. Here is a real example Guardfile I have in most
projects:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># frozen_string_literal: true</span>

<span class="n">ignore</span> <span class="sr">%r{.git</span><span class="se">\/</span><span class="sr">*}</span><span class="p">,</span>
       <span class="sr">%r{public</span><span class="se">\/</span><span class="sr">.*}</span><span class="p">,</span>
       <span class="sr">%r{solr</span><span class="se">\/</span><span class="sr">.*}</span><span class="p">,</span>
       <span class="sr">%r{vendor</span><span class="se">\/</span><span class="sr">.*}</span><span class="p">,</span>
       <span class="sr">%r{tmp</span><span class="se">\/</span><span class="sr">.*}</span><span class="p">,</span>
       <span class="sr">%r{log</span><span class="se">\/</span><span class="sr">.*}</span><span class="p">,</span>
       <span class="sr">%r{coverage</span><span class="se">\/</span><span class="sr">.*}</span>

<span class="n">guard</span><span class="p">(</span>
  <span class="ss">:minitest</span><span class="p">,</span>
  <span class="ss">spring: </span><span class="s1">'bin/rails test'</span><span class="p">,</span>
  <span class="ss">all_on_start: </span><span class="kp">true</span><span class="p">,</span>
  <span class="ss">all_after_pass: </span><span class="kp">true</span><span class="p">,</span>
  <span class="ss">grace_period: </span><span class="mf">3.0</span>
<span class="p">)</span> <span class="k">do</span>
  <span class="n">watch</span><span class="p">(</span><span class="sr">%r{^app/(.+)</span><span class="se">\.</span><span class="sr">rb$}</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">m</span><span class="o">|</span> <span class="s2">"test/</span><span class="si">#{</span><span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">_test.rb"</span> <span class="p">}</span>
  <span class="n">watch</span><span class="p">(</span><span class="sr">%r{^app/controllers/(.+)_controller</span><span class="se">\.</span><span class="sr">rb$}</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">m</span><span class="o">|</span> <span class="s2">"test/integration/</span><span class="si">#{</span><span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">_test.rb"</span> <span class="p">}</span>
  <span class="n">watch</span><span class="p">(</span><span class="sr">%r{^app/views/(.+)_mailer/.+}</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">m</span><span class="o">|</span> <span class="s2">"test/mailers/</span><span class="si">#{</span><span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">_mailer_test.rb"</span> <span class="p">}</span>
  <span class="n">watch</span><span class="p">(</span><span class="sr">%r{^test/test_helper</span><span class="se">\.</span><span class="sr">rb$}</span><span class="p">)</span> <span class="p">{</span> <span class="s1">'test'</span> <span class="p">}</span>
  <span class="n">watch</span><span class="p">(</span><span class="sr">%r{^test/.+_test</span><span class="se">\.</span><span class="sr">rb$}</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>When any tests fail, I’m immediately notified and I hop into the ‘testing’ tmux pane and can see
which tests are failing and fix it fast.</p>

<h3 id="5-amazing-print--pry">5. Amazing Print / Pry</h3>

<p>At the same time as I’m fixing tests or writing new tests, each time I save a file, Guard re-runs
the test giving me instant feedback. A lot of the time, I need to see what is being returned and
<a href="https://github.com/amazing-print/amazing_print">Amazing Print</a> comes in handy for this reason. I
can simply add the line <code class="language-plaintext highlighter-rouge">ap subject</code> to the test and save the file. Guard will rerun the test and
amazing print will print the results in full color. If I need to dig deeper, I can also drop in
<code class="language-plaintext highlighter-rouge">binding.pry</code>, and Guard will “suspend” execution and let me <a href="https://pry.github.io/">Pry</a> open the
code for a closer look.</p>

<h3 id="6-rubycop">6. Rubycop</h3>

<p><a href="https://docs.rubocop.org/rubocop/1.25/index.html">Rubocop</a> is a
static code analyzer and code formatter that helps me make sure I’m keeping inline with <a href="https://rubystyle.guide/">best
practices</a> thus increasing code health and maintainability. I have Rubocop
integrated with my Emacs config that allows me to see in real-time any violations and/or
recommendations on how the code could be written better. Plus paired with extensions like
rubocop-rails, rubocop-performance and rubocop-minitest, I can get recommendations immediately for
specific libraries and frameworks.</p>

<h3 id="7-simplecov">7. Simplecov</h3>

<p><a href="https://github.com/simplecov-ruby/simplecov">SimpleCov</a> let’s me see how well my tests are covering
the application code. SimplCov produces results in a very well organized html page where I can see pieces
of code that didn’t get “touched” marked in a shade of red. I can write tests
specifically that touches that code <em>or</em> remove the code if it’s not being used. It some cases, if
the code isn’t touched, it means it’s not being used and I can remove the code all together keeping
the project nice and tidy.</p>

<hr />

<p>There are quite a few other tools that I didn’t mention, but the above seven tools form a solid base on
what I use every day for Ruby/Rails development. I’ve enjoyed this particular setup for over a
decade and will mostly like continue this setup for the next decade.</p>]]></content><author><name></name></author><category term="ruby" /><summary type="html"><![CDATA[Over at the Shopify Enginneer Twitter account, an interesting question was posted that got me thinking about my favorite and most used Ruby/Rails tools. It’s nice to see what other devs are using so I thought I would share with you what I use the most on a daily basis. In a lot of cases, I’ve been using the same tools for over a decade.]]></summary></entry><entry><title type="html">2021: A Year In Review</title><link href="https://mattsears.com/articles/2021/12/31/2022-a-year-in-review/" rel="alternate" type="text/html" title="2021: A Year In Review" /><published>2021-12-31T00:00:00+00:00</published><updated>2021-12-31T00:00:00+00:00</updated><id>https://mattsears.com/articles/2021/12/31/2022-a-year-in-review</id><content type="html" xml:base="https://mattsears.com/articles/2021/12/31/2022-a-year-in-review/"><![CDATA[<p>For many of us, this past year has presented us with quite a few challenges. For
many personally, it’s been a few ups and a few downs both professionally and
personally. The affects of the pandemic continued to roll on this year much
like 2020. For much of the past year, it seemed like the movie Groundhog day -
wake up, walk to my office, work on something, and then go home. For this post,
I thought I’d shine a spotlight on a couple highlights and some
lowlights.<!--more--></p>

<h4 id="company-acquisition-complete">Company Acquisition Complete</h4>

<p>First and foremost, my consulting company of fourteen years was
<a href="/articles/2021/06/30/littlelines-acquired/">acquired</a> and completed the full
turn-over in June. I am so incredibly proud that the transition was a huge
success and I can’t be more excited about the results. It was a great learning
experience to know what it means to prepare, negotiate, and plan for a
acquisition successfully.</p>

<p><img src="/assets/images/fullsize/me-at-hybridconf.jpg" alt="Me at HybridConf" /></p>

<p>Running and operating a technology consulting company over the past 14 years has
been the biggest journey of my life. I could have never imagined what the
company evolved to when I first decided to quit my “big tech” job and
venture out on my own. I’ve learned a tremendous amount, not only in all
aspects of business, but in interpersonal skills, leadership, how to roll with
the punches and the importance of celebrating milestones just to name a few.</p>

<h4 id="peace-out-eyesight">Peace out Eyesight</h4>

<p>Now for the lowlight of the year, in early summer, my eye vision suddenly
started <a href="/articles/2021/08/30/taking-care-of-your-vision/">failing</a> in a big
way - no doubt from heavy screen use from the pandemic. I was forced off all screens
for what felt like an eternity. I’m so thankful as I sit here and write this
post in my beloved Emacs, that I’m back armed with my new glasses ready to
work. It’s a life-altering event to say the least. I’ve joined the exclusive
club of people that are always looking for their glasses.</p>

<p><img src="/assets/images/fullsize/me-at-beach-2021.jpg" alt="Me at beach 2021" /></p>

<p class="w-full  text-center text-sm italic">
  Relaxing at the beach in the San Juan islands
</p>

<p>The positive side effect of losing temporary eyesight is that it forced me off
the screens (and also social-media) and back in touch with the analog
life. Getting back to nature, I gained a real appreciation for the gifts that
have been here all along. I spent many days at the beach, hiking,
paddle-boarding and road trips. Not being tethered to my phone all the time
was absolutely liberating. Even though I’ve gained my eyesight back, I
continue to spend less time online and more time being present in real life.</p>

<h4 id="hotwire-ruby-on-rails-view-components-and-tailwind-css">Hotwire, Ruby on Rails, View Components, and Tailwind CSS</h4>

<p>Most posts this past year have been about these topics and most of the year I
spent writing and learning on what I called the <a href="/articles/2021/03/30/hotwire-view-component-tailwind-css-a-new-era-in-ruby-on-rails-development/">new
era</a>
of Ruby on Rails development. It is fantastic. Many thanks to the fine
folks at Basecamp and Rails team for ushering in a new way of writing Rails
applications. Those that know me, know I’ve never been a fan of writing SPA apps and the amount of
JavaScript required is absurd. So when Hotwire and Turbo were released, it was a
very welcome addition.</p>

<p><img src="/assets/images/fullsize/hotwire-new-era.jpg" alt="Hotwire new era" /></p>

<p>Paired with <a href="https://viewcomponent.org/">ViewComponents</a>, it feels like another
natural addition to the Rails toolbox. Throw in
<a href="https://stimulus.hotwired.dev/">Stimulus</a> and <a href="https://tailwindcss.com/">Tailwind
CSS</a>, it feels like discovering the joy of web
development all over again.</p>

<h4 id="favorite-books-and-podcasts">Favorite books and podcasts</h4>

<p>I’ve written about a <a href="/articles/2021/04/25/two-simple-books-to-wealth/">couple
books</a> on finance that have
really affect my outlook on investing in a very positive way. In addition to
these books, I’ve listened to many many books and podcasts while my eyesight was
on hiatus. Here are just a few of my favorite this year.</p>

<h4 id="books">Books</h4>

<ol>
  <li><a href="https://www.amazon.com/Notes-Nervous-Planet-Matt-Haig/dp/014313342X">Notes on a Nervous Planet</a></li>
  <li><a href="https://www.amazon.com/Traction-Get-Grip-Your-Business/dp/1936661837">Traction: Get a Grip on Your Business</a></li>
  <li><a href="https://www.amazon.com/Unfu-Yourself-Your-Head-into/dp/0062803832">Unfu*k Yourself: Get Out of Your Head and into Your Life</a></li>
  <li><a href="https://www.amazon.com/Psychology-Money-Timeless-lessons-happiness/dp/0857197681">The Psychology of Money: Timeless lessons on wealth, greed, and happiness</a></li>
</ol>

<p><img src="/assets/images/fullsize/notes-on-nervous-planet-2021.jpg" alt="Notes on a Nervous Planet 2021" /></p>

<h4 id="podcasts">Podcasts</h4>

<ol>
  <li><a href="https://slate.com/podcasts/one-year/s1/1977">One Year</a></li>
  <li><a href="https://microconfpodcast.com/">MicroConf On Air</a></li>
  <li><a href="https://officeladies.com/">Office Ladies</a></li>
  <li><a href="https://www.rework.fm/">The Rework Podcast</a></li>
</ol>

<h4 id="what-i-look-forward-to-in-2022">What I look forward to in 2022</h4>

<p>I generally don’t set new year resolutions or any new year goals for that
matter. I believe that should be done throughout the year. But, what I like to
do is set intentions for the year in hopes to shape and navigate the year to
come. So this year, I want to set an intention to focus on mental and physical
health first and foremost.</p>

<p>I really look forward to doing what I love to do. For work, this
means creating and building things from my own ideas in hopes it will help people in
their own lives and businesses. For my mental well-being, I want to continue
connecting with nature and continue my exercise regiment. Last, but not least, I
want to make new and stronger connections to friends and loved ones in this
new year. I’m really hopeful we all can make stronger connections again this year.</p>

<p>Happy New Year everyone! I hope you all have a happy and healthy 2020.</p>]]></content><author><name></name></author><category term="misc" /><summary type="html"><![CDATA[For many of us, this past year has presented us with quite a few challenges. For many personally, it’s been a few ups and a few downs both professionally and personally. The affects of the pandemic continued to roll on this year much like 2020. For much of the past year, it seemed like the movie Groundhog day - wake up, walk to my office, work on something, and then go home. For this post, I thought I’d shine a spotlight on a couple highlights and some lowlights.]]></summary></entry><entry><title type="html">To Gem Or Not To Gem</title><link href="https://mattsears.com/articles/2021/11/29/to-gem-or-not-to-gem/" rel="alternate" type="text/html" title="To Gem Or Not To Gem" /><published>2021-11-29T23:21:00+00:00</published><updated>2021-11-29T23:21:00+00:00</updated><id>https://mattsears.com/articles/2021/11/29/to-gem-or-not-to-gem</id><content type="html" xml:base="https://mattsears.com/articles/2021/11/29/to-gem-or-not-to-gem/"><![CDATA[<p>When it comes to running a Rails project for the long-term, one strong indicator
for success is gem <em>decision</em>. I’ve worked on dozens and dozens of Rails
applications during my time as a consultant and often times a client’s project
would be either be suffering from poor performance or is too difficult to
maintain and progress has slowed down to crawl. <!--more-->The first thing I typically
looked at is the Gemfile. It’s more common than not that there are <em>too many</em>
gems.</p>

<p>This is especially true for new Rails developers - too eager to reach for a gem
for every new feature they write. When there are too many gems, the app will run
slower since there are more lines of code to process. Why is this? Typically gem
authors need to accommodate for a variety of factors. Factors like Ruby
versions, database types, or web frameworks like Sinatra. What this means is
there is a lot of extra code in that gem that will never be used by our
application. Many times, I’ve seen a Rails app just use on method from a single
gem!</p>

<h3 id="three-questions-i-ask-when-deciding-to-use-a-gem-or-not">Three questions I ask when deciding to use a gem or not:</h3>

<h4 id="1-is-it-currently-being-maintained">1. Is it currently being maintained?</h4>

<p>Take a look at the source code on Github or Gitlab. What is the date of the last
commit? Does the author explicitly state that the gem is no longer maintained?
If there hasn’t been a commit in the last year, it’s most likely not being
updated. So we can’t expect bug fixes or security updates in the near future. It
will may also mean that we risk preventing other gems from being updated. For
example, running <code class="language-plaintext highlighter-rouge">bundle update</code> on our Rails project may not run since the
unmaintained gem depends on other older gem versions.</p>

<h4 id="2-what-is-the-size-of-the-gem">2. What is the size of the gem?</h4>

<p>How big is the project? What other gems does it depend on? Browse through
the source and get a rough idea about the amount of code. There might be a lot
of code to handle a variety of environments <em>or</em> it may not be as organized or
designed well. Why is this important? More gems means more Ruby and more Ruby
means a slower running app.</p>

<h4 id="3-how-much-of-the-gem-do-we-need-to-utilize">3. How much of the gem do we need to utilize?</h4>

<p>What do I need from this gem to get our feature complete? Do we just need one or
two small things to get the job done or do we need something more comprehensive like
<a href="https://github.com/heartcombo/devise">Devise</a> or
<a href="https://viewcomponent.org">ViewComponents</a>. Obviously, if we need a gem that is
more comprehensive, then we should use the gem. A gem like ViewComponents is a
large project and would require a lot of code to mimic the functionality and
it’s more or less closer to the core of our application.</p>

<h3 id="case-study">Case Study</h3>

<p>I recently had the need for the ability to save a <em>draft</em> of data before saving
it to the real database record. Simply put, I need to stash a set of data that
mocked my real ActiveRecord model’s schema and save it to a database until the
users decides to publish it.</p>

<p>After some searching, I found a couple gems that do exactly what I
need. However, none of them have been updated in the last year. The most popular
of the gems is actively looking for a new maintainer and it has a bunch of
overly complicated code that I most likely will never need. In my case, I only
need to save a draft and publish the draft - that’s it.</p>

<p>If you haven’t guessed by now, I’ve decided not to use any gem and write my own
code to do what I need. I’m going to approach this as a reusable code in
case we want to use drafts in our other models. I’ve also looked at the source
code of the gems to get ideas and use them in my own code.</p>

<p>Let’s create a concern called <em>Draftable</em>:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># apps/models/concerns/draftable</span>

<span class="k">module</span> <span class="nn">Draftable</span>
 <span class="kp">extend</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Concern</span>

 <span class="n">included</span> <span class="k">do</span>
   <span class="n">has_one</span> <span class="ss">:draft</span><span class="p">,</span> <span class="ss">as: :draftable</span><span class="p">,</span> <span class="ss">dependent: :destroy</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">has_draft?</span>
   <span class="no">Draft</span><span class="p">.</span><span class="nf">exists?</span><span class="p">(</span><span class="ss">draftable_id: </span><span class="nb">id</span><span class="p">)</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">save_draft</span><span class="p">(</span><span class="n">params</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span>
   <span class="k">return</span> <span class="kp">false</span> <span class="k">if</span> <span class="n">new_record?</span>

   <span class="k">if</span> <span class="n">has_draft?</span>
     <span class="n">update_draft</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
   <span class="k">else</span>
     <span class="n">create_draft</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
   <span class="k">end</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">publish!</span>
   <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="p">.</span><span class="nf">transaction</span> <span class="k">do</span>
     <span class="nb">self</span><span class="p">.</span><span class="nf">attributes</span> <span class="o">=</span> <span class="n">draft</span><span class="p">.</span><span class="nf">reify</span><span class="p">.</span><span class="nf">attributes</span>
     <span class="nb">self</span><span class="p">.</span><span class="nf">save</span>
     <span class="nb">self</span><span class="p">.</span><span class="nf">reload</span>
     <span class="n">draft</span><span class="p">.</span><span class="nf">destroy</span>
   <span class="k">end</span>
 <span class="k">end</span>

 <span class="kp">private</span>

 <span class="k">def</span> <span class="nf">create_draft</span><span class="p">(</span><span class="n">_params</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span>
   <span class="n">with_transaction_returning_status</span> <span class="k">do</span>
     <span class="n">draft</span> <span class="o">||=</span> <span class="no">Draft</span><span class="p">.</span><span class="nf">new</span>
     <span class="n">draft</span><span class="p">.</span><span class="nf">object</span> <span class="o">=</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">JSON</span><span class="p">.</span><span class="nf">encode</span><span class="p">(</span><span class="n">attributes</span><span class="p">)</span>
     <span class="n">draft</span><span class="p">.</span><span class="nf">draftable_id</span> <span class="o">=</span> <span class="nb">id</span>
     <span class="n">draft</span><span class="p">.</span><span class="nf">draftable_type</span> <span class="o">=</span> <span class="nb">self</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span>
     <span class="n">draft</span><span class="p">.</span><span class="nf">save</span>
   <span class="k">end</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">update_draft</span><span class="p">(</span><span class="n">params</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span>
   <span class="n">with_transaction_returning_status</span> <span class="k">do</span>
     <span class="n">values</span> <span class="o">=</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">JSON</span><span class="p">.</span><span class="nf">decode</span><span class="p">(</span><span class="n">draft</span><span class="p">.</span><span class="nf">object</span><span class="p">)</span>

     <span class="n">params</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="o">|</span>
       <span class="n">values</span><span class="p">[</span><span class="n">key</span><span class="p">.</span><span class="nf">to_s</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
     <span class="k">end</span>

     <span class="n">draft</span><span class="p">.</span><span class="nf">object</span> <span class="o">=</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">JSON</span><span class="p">.</span><span class="nf">encode</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
     <span class="n">draft</span><span class="p">.</span><span class="nf">save</span>
   <span class="k">end</span>
 <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>We’ve made this concern so that any model can have a <em>draft</em>. Here, we’re
storing data in the <code class="language-plaintext highlighter-rouge">object</code> field using JSON objects. We do this with a
polymorphic relationship to a Draft model:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/model/draft.rb</span>

<span class="k">class</span> <span class="nc">Draft</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="n">belongs_to</span> <span class="ss">:draftable</span><span class="p">,</span> <span class="ss">polymorphic: </span><span class="kp">true</span>

  <span class="n">validates</span> <span class="ss">:object</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>

  <span class="k">def</span> <span class="nf">reify</span>
    <span class="n">attrs</span> <span class="o">=</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">JSON</span><span class="p">.</span><span class="nf">decode</span><span class="p">(</span><span class="n">object</span><span class="p">)</span>

    <span class="n">attrs</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="o">|</span>
      <span class="k">if</span> <span class="n">draftable</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"</span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">="</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">key</span><span class="p">.</span><span class="nf">end_with?</span><span class="p">(</span><span class="s2">"_count"</span><span class="p">)</span>
        <span class="n">draftable</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="s2">"</span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">="</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
      <span class="k">end</span>
    <span class="k">end</span>
    <span class="n">draftable</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Now we can make any model have a draft. For example, let’s say we’re building a
blog and we have a Post model that holds the article. I can simply include a
<code class="language-plaintext highlighter-rouge">Draftable</code> module in my model:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/models/post.rb</span>

<span class="k">class</span> <span class="nc">Post</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="kp">include</span> <span class="no">Draftable</span>
  <span class="o">...</span>
<span class="k">end</span>
</code></pre></div></div>

<p>With that, we can do things like <code class="language-plaintext highlighter-rouge">post.save_draft(body: 'First draft of the
article')</code> to save a draft and <code class="language-plaintext highlighter-rouge">@post.publish!</code> to save the draft data to the
<code class="language-plaintext highlighter-rouge">posts</code> table.</p>

<p>To summarize, the point of creating <code class="language-plaintext highlighter-rouge">Draftable</code> is to illustrate the decision
<em>not to use</em> a gem even if one exists. With roughly a hundred lines of code (not
counting our tests), we’re able to complete our feature and extend our app
functionality by allowing any model to have a draft. In addition, we’re not
dependent on another gem or it’s dependencies. We’re using <strong>less</strong> Ruby and so  our
app is lean and more maintainable.</p>]]></content><author><name>Matt Sears</name></author><category term="development" /><summary type="html"><![CDATA[When it comes to running a Rails project for the long-term, one strong indicator for success is gem decision. I’ve worked on dozens and dozens of Rails applications during my time as a consultant and often times a client’s project would be either be suffering from poor performance or is too difficult to maintain and progress has slowed down to crawl.]]></summary></entry></feed>