<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="https://www.w3.org/2005/Atom">

 <title>A Year of Commits</title>
 <link href="https://jakeyesbeck.com/atom.xml" rel="self"/>
 <link href="https://jakeyesbeck.com/"/>
 <updated>2021-04-12T08:00:51-04:00</updated>
 <id>https://jakeyesbeck.com/</id>
 <author>
   <name>Jake Yesbeck</name>
   <email>yesbeckjs@gmail.com</email>
 </author>

 
 <entry>
   <title>Why You Should Avoid Models in Rails Migrations</title>
   <link href="https://jakeyesbeck.com/2021/04/10/avoid-models-in-migrations/"/>
   <updated>2021-04-10T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2021/04/10/avoid-models-in-migrations</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/images/avoid-models-in-rails-migrations.jpg&quot; alt=&quot;Avoid Models in Rails Migrations&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;humble-beginnings&quot;&gt;Humble Beginnings&lt;/h2&gt;

&lt;p&gt;A simple Rails application exists with two models, &lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Authors&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After some domestic success, this simple Rails app goes international. A new column
is required on the &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; table: &lt;code class=&quot;highlighter-rouge&quot;&gt;country&lt;/code&gt; to denote which country published the
&lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;a-reasonable-migration&quot;&gt;A Reasonable Migration&lt;/h2&gt;

&lt;p&gt;To preserve data integrity, the &lt;code class=&quot;highlighter-rouge&quot;&gt;country&lt;/code&gt; column should not allow &lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt; since
&lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt; isn’t a country. Existing &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; also need to have a &lt;code class=&quot;highlighter-rouge&quot;&gt;country&lt;/code&gt; set.
This is all accomplished within a single migration in 3 steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Add a column&lt;/li&gt;
  &lt;li&gt;Update column for existing &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; with a reasonable value&lt;/li&gt;
  &lt;li&gt;Add a constraint that the column can not be &lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddCountryToBooks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;up&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;length: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;country: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;US&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;change_column_null&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;down&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remove_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This migration does the job but has hidden implications. A developer working in
isolation may never run into the trap lurking in this code, but a team could.&lt;/p&gt;

&lt;h2 id=&quot;working-with-others&quot;&gt;Working with Others&lt;/h2&gt;

&lt;p&gt;Two developers work on this application, divvying up the wild world of
&lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;authors&lt;/code&gt; but maintaining healthy work life balances. One developer
goes on vacation and has a surprise waiting for them when they return.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Developer 1 👩‍💻&lt;/th&gt;
      &lt;th&gt;Developer 2 👨‍💻&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Day 1&lt;/td&gt;
      &lt;td&gt;Write Code&lt;/td&gt;
      &lt;td&gt;Write Code&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Day 2&lt;/td&gt;
      &lt;td&gt;😎️ Time Off&lt;/td&gt;
      &lt;td&gt;🏗️ Create Migration&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Day 3&lt;/td&gt;
      &lt;td&gt;😎️ Time Off&lt;/td&gt;
      &lt;td&gt;📛️ Rename Class&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Day 4&lt;/td&gt;
      &lt;td&gt;😎️ Time Off&lt;/td&gt;
      &lt;td&gt;Write Code&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Day 5&lt;/td&gt;
      &lt;td&gt;Run Migrations -&amp;gt; 🔥️ Error&lt;/td&gt;
      &lt;td&gt;Write Code&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;While Developer 1 was away, the Developer 2 was busy. They wrote the above migration,
updated existing data and then a new feature request was completed: A model
rename.&lt;/p&gt;

&lt;p&gt;Developer 1 returns, updates their local environment, and runs &lt;code class=&quot;highlighter-rouge&quot;&gt;rake db:migrate&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 20210407191819 AddCountryToBooks: migrating &lt;span class=&quot;o&quot;&gt;===================&lt;/span&gt;
-- add_column&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;:books, :country, :string, &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;:length&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;gt;2&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
   -&amp;gt; 0.0015s
rake aborted!
StandardError: An error has occurred, this and all later migrations
canceled:

uninitialized constant AddCountryToBooks::Book
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; was renamed to &lt;code class=&quot;highlighter-rouge&quot;&gt;Novel&lt;/code&gt; breaking the previous migration.&lt;/p&gt;

&lt;h2 id=&quot;avoiding-models&quot;&gt;Avoiding Models&lt;/h2&gt;

&lt;h3 id=&quot;using-sql&quot;&gt;Using SQL&lt;/h3&gt;

&lt;p&gt;When used correctly, Rails migrations can count on the database being in an expected
state. The application code moves from commit to commit but database structure
(should) only change with migrations. Therefore, even if the &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; class is now
&lt;code class=&quot;highlighter-rouge&quot;&gt;Novel&lt;/code&gt;, the database table &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; still exists at the time of the
&lt;code class=&quot;highlighter-rouge&quot;&gt;AddCountryToBooks&lt;/code&gt; migration.&lt;/p&gt;

&lt;p&gt;Instead of &lt;code class=&quot;highlighter-rouge&quot;&gt;Book.update_all&lt;/code&gt;, writing an update query in SQL and using the base
&lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; connection ensures this migration survives model changes like
a rename. Because we can count on the state of the database structure,
referring to the &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; table is safe while referring to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; model may
not be.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddCountryToBooks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;up&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;length: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;UPDATE books SET country = &#39;US&#39;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;change_column_null&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;down&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remove_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;using-temporary-models&quot;&gt;Using Temporary Models&lt;/h3&gt;

&lt;p&gt;If writing SQL isn’t ideal, a temporary model can be used within the migration.
Here, a new &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; model is defined to manipulate the &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; table. Even if
&lt;code class=&quot;highlighter-rouge&quot;&gt;app/models/book.rb&lt;/code&gt; has been changed to &lt;code class=&quot;highlighter-rouge&quot;&gt;app/models/novel.rb&lt;/code&gt;, this definition
of &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; will be valid within the scope of this migration.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddCountryToBooks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;up&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;length: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;country: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;US&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;change_column_null&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;down&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remove_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Either of these migration will run correctly for Developer 1 no matter how many model
renames happened while they were on vacation.&lt;/p&gt;

&lt;h2 id=&quot;problem-at-scale&quot;&gt;Problem at Scale&lt;/h2&gt;

&lt;p&gt;It might not seem like that big of a deal to have a single broken migration.
But, within a larger team or with more complex migrations, this can easily
become a painful hurdle a team needs to navigate.&lt;/p&gt;

&lt;p&gt;Allowing migrations to rely on only the database as a source of truth enables
all developers on the team to run migrations without issue. That is until
the database or team inevitably get too large and people do database restores
instead of running migrations, then this issue is far less common.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Making RSpec Tests More Robust</title>
   <link href="https://jakeyesbeck.com/2020/07/19/making-rspec-tests-more-robust/"/>
   <updated>2020-07-19T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2020/07/19/making-rspec-tests-more-robust</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/images/robust-rspec-tests.jpg&quot; alt=&quot;Robust RSpec Tests&quot; /&gt;&lt;/p&gt;

&lt;p&gt;RSpec is a popular framework for testing Ruby code. With an &lt;code class=&quot;highlighter-rouge&quot;&gt;expect&lt;/code&gt;
assertion, a developer can make sure their code calls the proper method or
an acceptable result is returned. The &lt;code class=&quot;highlighter-rouge&quot;&gt;expect().to receive&lt;/code&gt; matcher in a test
overrides the default implementation and can cause some unintended side
effects.&lt;/p&gt;

&lt;p&gt;To demonstrate this potential problem, assume a very simple API client exists that
can update models.&lt;/p&gt;

&lt;h2 id=&quot;testing-an-api-client&quot;&gt;Testing an API Client&lt;/h2&gt;

&lt;p&gt;An example &lt;code class=&quot;highlighter-rouge&quot;&gt;api_client.rb&lt;/code&gt; class defines a single &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method that calls the underlying API with a &lt;code class=&quot;highlighter-rouge&quot;&gt;Faraday&lt;/code&gt; connection.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# api_client.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;APIClient&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Faraday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;https://some-cool-api.com&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Inheriting from &lt;code class=&quot;highlighter-rouge&quot;&gt;api_client.rb&lt;/code&gt; is &lt;code class=&quot;highlighter-rouge&quot;&gt;my_model.rb&lt;/code&gt; which defines an &lt;code class=&quot;highlighter-rouge&quot;&gt;update&lt;/code&gt;
method.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# my_model.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;APIClient&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/my_models/1&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A typical test for the &lt;code class=&quot;highlighter-rouge&quot;&gt;update&lt;/code&gt; method on &lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel&lt;/code&gt; in RSpec might look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# my_model_spec.rb&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyModel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;update&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;updates the model&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foo: :bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;subject&lt;/code&gt; in the above test is &lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel.new&lt;/code&gt; and is expected to receive the
method &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt;. Since &lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel#update&lt;/code&gt; calls the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method, this seems like
a reasonable test.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec my_model_spec.rb
.

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.0054 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.07101 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 0 failures
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Running the test produces a passing result, the &lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel&lt;/code&gt; class calls
its parent method correctly and all is well. Until something changes that the
test is unable to detect.&lt;/p&gt;

&lt;h2 id=&quot;breaking-the-contract&quot;&gt;Breaking the Contract&lt;/h2&gt;

&lt;p&gt;If &lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel&lt;/code&gt;’s contract changes, the test should fail. If, for
instance, the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method on the &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient&lt;/code&gt; class is removed or commented
out, the &lt;code class=&quot;highlighter-rouge&quot;&gt;update&lt;/code&gt; method on &lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel&lt;/code&gt; would no longer work.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# api_client.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;APIClient&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# def put(url, body)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#   client.put(url, body)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# end&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Faraday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;https://some-cool-api.com&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, the test still passes despite this method being removed.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec my_model_spec.rb
.

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00523 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.0699 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 0 failures
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So what is going on here?&lt;/p&gt;

&lt;p&gt;The culprit is this line: &lt;code class=&quot;highlighter-rouge&quot;&gt;expect(subject).to receive(:put)&lt;/code&gt;. The test happily
accepts the call to &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient#put&lt;/code&gt; despite it being removed. This is
obviously problematic and, in a worst case scenario, could lead to an outage if
a test suite is the only gateway to production code.&lt;/p&gt;

&lt;p&gt;Starting an &lt;code class=&quot;highlighter-rouge&quot;&gt;irb&lt;/code&gt; repl and calling the problematic method reveals that the code
is no longer working despite the test’s result.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;MyModel:0x00005585f950ca10&amp;gt;&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;002&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;foo: :bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Traceback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;most&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/home/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yez&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rvm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubies&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ruby&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&amp;lt;main&amp;gt;&#39;
        2: from (irb):2
        1: from /tmp/foo.rb:8:in `&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;
NoMethodError (undefined method `put&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;MyModel:0x00005585f950ca10&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Since this code communicates to an API, validating that the underlying &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt;
request is done successfully can be tricky. Unlike tests in a Rails application,
&lt;code class=&quot;highlighter-rouge&quot;&gt;MyModel#update&lt;/code&gt; can not be validated in a local database.&lt;/p&gt;

&lt;p&gt;With a passing test and broken code, it is clear that wrong thing has been tested.
As is, the test only asserts that a method calls another method and happily ignores
everything else. One possible solution could be to add &lt;code class=&quot;highlighter-rouge&quot;&gt;and_call_original&lt;/code&gt; to
the end of the &lt;code class=&quot;highlighter-rouge&quot;&gt;expect(). to receive&lt;/code&gt; line. This would make sure the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt;
method is really there but would also make a real HTTP request in a test (which
is generally bad practice).&lt;/p&gt;

&lt;p&gt;An easy way to make this test more robust without going overboard is to stub
the response of the HTTP client. Instead of mocking the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method in &lt;code class=&quot;highlighter-rouge&quot;&gt;api_client.rb&lt;/code&gt;,
tools like &lt;code class=&quot;highlighter-rouge&quot;&gt;webmock&lt;/code&gt; can be utilized to stub the &lt;code class=&quot;highlighter-rouge&quot;&gt;Faraday&lt;/code&gt; response. This
enables the code to fake an HTTP request instead of of calling out to
&lt;code class=&quot;highlighter-rouge&quot;&gt;https://some-cool-api.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;testing-with-webmock&quot;&gt;Testing with &lt;code class=&quot;highlighter-rouge&quot;&gt;Webmock&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;webmock&lt;/code&gt; gem allows developers to define custom responses for specific HTTP
requests.&lt;/p&gt;

&lt;p&gt;After installing the gem with &lt;code class=&quot;highlighter-rouge&quot;&gt;gem install webmock&lt;/code&gt;, a stub can be written that
matches the URL and request body to return a specific response.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;WebMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stub_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;https://some-cool-api.com/my_models/1&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;body: &lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/foo.*bar$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;body: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;{ &quot;success&quot;: true }&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In this case the stubbed response is &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt; and will be returned
for any &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; requests to &lt;code class=&quot;highlighter-rouge&quot;&gt;https://some-cool-api.com/my_models/1&lt;/code&gt; with a request body
matching &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt; followed by &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;. This stub can be added in a shared file or
at the beginning of &lt;code class=&quot;highlighter-rouge&quot;&gt;my_model_spec.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With the stub added, &lt;code class=&quot;highlighter-rouge&quot;&gt;my_model_spec.rb&lt;/code&gt; can be updated to remove the old
&lt;code class=&quot;highlighter-rouge&quot;&gt;expect().to receive&lt;/code&gt; line and instead validate the response.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# my_model_spec.rb&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyModel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;update&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;updates the model&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foo: :bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;success&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The stub works and running &lt;code class=&quot;highlighter-rouge&quot;&gt;my_model_spec.rb&lt;/code&gt; shows the test passes.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec my_model_spec.rb
.

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00531 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.33028 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 0 failures
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, if &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient&lt;/code&gt; is changed in the same way as before, the test will
appropriately fail and alert the developer that the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method does not
exist.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# api_client.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;APIClient&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# def put(url, body)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#   client.put(url, body)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# end&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Faraday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;https://some-cool-api.com&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec my_model_spec.rb
F

Failures:

  1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; MyModel update updates the model
     Failure/Error: put&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/my_models/1&#39;&lt;/span&gt;, body&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

     NoMethodError:
       undefined method &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;put&lt;span class=&quot;s1&quot;&gt;&#39; for #&amp;lt;MyModel:0x000055f148a80018&amp;gt;
       Did you mean?  puts
                      putc
     # ./my_model_spec.rb:17:in `update&#39;&lt;/span&gt;
     &lt;span class=&quot;c&quot;&gt;# ./my_model_spec.rb:30:in `block (3 levels) in &amp;lt;top (required)&amp;gt;&#39;&lt;/span&gt;

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00298 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.4606 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 1 failure
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;stricter-settings&quot;&gt;Stricter Settings&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;RSpec&lt;/code&gt; allows developers to enable the flag &lt;code class=&quot;highlighter-rouge&quot;&gt;verify_partial_doubles&lt;/code&gt; which
will cause the original test to fail when the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method is removed.  This setting
is turned off by default.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;RSpec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mock_with&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rspec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;verify_partial_doubles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With this setting in place, running the original code and test produces
a failing result.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# api_client.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;APIClient&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# def put(url, body)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#   client.put(url, body)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# end&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Faraday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;https://some-cool-api.com&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# my_model_spec.rb&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyModel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;update&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;updates the model&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foo: :bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec my_model_spec.rb
F

Failures:

  1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; MyModel update updates the model
     Failure/Error: expect&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;subject&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.to receive&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;:put&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;c&quot;&gt;#&amp;lt;MyModel:0x000055d4a4f740a8&amp;gt; does not implement: put&lt;/span&gt;
     &lt;span class=&quot;c&quot;&gt;# ./my_model_spec.rb:35:in `block (3 levels) in &amp;lt;top (required)&amp;gt;&#39;&lt;/span&gt;

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00877 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.46471 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 1 failure
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This alternative does not require the use of a new gem and will fail correctly
if the underlying contract is removed. However, if the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method or any
layer between it and the API request changes, this test is not guaranteed to
save a developer from that issue.&lt;/p&gt;

&lt;p&gt;Determining what layer to mock and what to explicitly test is a very case by case
basis.&lt;/p&gt;

&lt;h2 id=&quot;keep-tests-robust&quot;&gt;Keep Tests Robust&lt;/h2&gt;

&lt;p&gt;Mocks and stubs in RSpec allow developers to make important assertions about
their code. Unfortunately, mocking can also cause false positives when
modifying real code.&lt;/p&gt;

&lt;p&gt;Validating that the proper settings are in an application is a great first step
towards more a more robust test suite.&lt;/p&gt;

&lt;p&gt;Stubbing the response for the underlying API in this example enables a much
more robust test that can alert developers when they make breaking changes.
However, if the API response from &lt;code class=&quot;highlighter-rouge&quot;&gt;https://some-cool-api.com&lt;/code&gt; changes, the
&lt;code class=&quot;highlighter-rouge&quot;&gt;webmock&lt;/code&gt; stub must be updated.&lt;/p&gt;

&lt;p&gt;Stubbing and mocking tools should be used on a case by case basis. In the case
of testing a third party API integration, providing canned responses in the test
suite makes sense. In other “normal” Ruby or Rails tests, &lt;a href=&quot;https://jakeyesbeck.com/2017/07/12/a-few-rspec-helpful-hints/#verifying-doubles&quot;&gt;verifying doubles&lt;/a&gt;
or other built in RSpec matchers could be all that’s needed.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Ruby Processes and Threads - Configuring a Web Server</title>
   <link href="https://jakeyesbeck.com/2019/06/18/ruby-processes-and-threads/"/>
   <updated>2019-06-18T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2019/06/18/ruby-processes-and-threads</id>
   <content type="html">&lt;p&gt;Multiple popular Ruby web servers exist. Each Ruby application is different and the ultimate &lt;strong&gt;tl;dr&lt;/strong&gt; for configuring a web server is: &lt;em&gt;it depends.&lt;/em&gt; This post will not prescribe one web server or configuration over another and will instead explain internal components most popular servers contain.&lt;/p&gt;

&lt;p&gt;In order to facilitate more than one request at a time, a Ruby web server implements &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt;, or both. These tools are used to enable concurrency and are beneficial in different ways.&lt;/p&gt;

&lt;h3 id=&quot;threads&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; in Ruby are a solution for concurrent programming and can alleviate slow downs due to blocking code. This blocking is usually referred to as “I/O” or Input/Output blocking and occurs when a program must reach out for additional information.  External API calls, reading from disk, and querying a database are all examples of blocking operations. When using multiple &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;, an application can continue to function while one &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; is waiting.&lt;/p&gt;

&lt;p&gt;Most Ruby code in the wild is running on MRI (if you’re not sure what you’re using, there is a good chance this is what you use). Because of this, Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; are subject to the Global Interpreter Lock or &lt;code class=&quot;highlighter-rouge&quot;&gt;GIL&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;GIL&lt;/code&gt; prevents any two &lt;code class=&quot;highlighter-rouge&quot;&gt;threads&lt;/code&gt; in the same &lt;code class=&quot;highlighter-rouge&quot;&gt;process&lt;/code&gt; from running at exactly the same time making true parallelism not possible.&lt;/p&gt;

&lt;h3 id=&quot;processes&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;One way to allow for true parallelism in Ruby is to use multiple &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt;. A Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Process&lt;/code&gt; is the instance of an application or a forked copy. In a traditional Rails application, each &lt;code class=&quot;highlighter-rouge&quot;&gt;Process&lt;/code&gt; contains all the build up, initialization, and resource allocation the app will need.&lt;/p&gt;

&lt;p&gt;Running multiple &lt;code class=&quot;highlighter-rouge&quot;&gt;Proccesses&lt;/code&gt; can enable more efficient usage of some server resources like the CPU but is not without its downsides. Because each &lt;code class=&quot;highlighter-rouge&quot;&gt;process&lt;/code&gt; must boot and provision an entire app, memory usage or database connection saturation can become a limiting factor.&lt;/p&gt;

&lt;h2 id=&quot;tempering-the-metal&quot;&gt;Tempering the Metal&lt;/h2&gt;

&lt;p&gt;When configuring on a web server, an application’s request shape is the most important factor to consider. Web application requests can demand I/O operations, computationally taxing operations, both, or neither.&lt;/p&gt;

&lt;p&gt;This example app has one controller named &lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller&lt;/code&gt; and a single route defined: &lt;code class=&quot;highlighter-rouge&quot;&gt;index&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;indexcontrollerrb&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller.rb&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IndexController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;interval_sleep&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;hello: :there&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;interval_sleep&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To emulate I/O blocking, this code uses a &lt;code class=&quot;highlighter-rouge&quot;&gt;sleep&lt;/code&gt; call to randomly stall between &lt;code class=&quot;highlighter-rouge&quot;&gt;40ms&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;200ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This application’s web server is &lt;code class=&quot;highlighter-rouge&quot;&gt;Puma&lt;/code&gt; since it gives allows scaling of both &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; independently.&lt;/p&gt;

&lt;p&gt;Most of the configuration is unchanged and the following two lines are all that will change during this testing:&lt;/p&gt;

&lt;h3 id=&quot;configpumarb&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;config/puma.rb&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;threads_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;RAILS_MAX_THREADS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;WEB_CONCURRENCY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here the configuration sets the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; the application can use to fulfill requests.&lt;/p&gt;

&lt;p&gt;With the configuration set and ready to go, the server is started with &lt;code class=&quot;highlighter-rouge&quot;&gt;bundle exec rails server&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;under-siege&quot;&gt;Under Siege&lt;/h2&gt;

&lt;p&gt;Now that the application code is written and the web server is configured, it can receive requests. To measure throughput, latency, memory usage, and CPU utilization, the tool Siege is used.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://linux.die.net/man/1/siege&quot;&gt;Siege&lt;/a&gt; is a benchmarking tool that has a very simple interface. Siege can be run via a small bash script with a few configurable options for each test.&lt;/p&gt;

&lt;h3 id=&quot;binsiegesh&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bin/siege.sh&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#! /bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;CONCURRENCY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;30
&lt;span class=&quot;nv&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;http://localhost:3000/index&#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CONTENT_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;application/json&#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;REPS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;20

siege -b --content-type &lt;span class=&quot;nv&quot;&gt;$CONTENT_TYPE&lt;/span&gt; -c &lt;span class=&quot;nv&quot;&gt;$CONCURRENCY&lt;/span&gt; -r &lt;span class=&quot;nv&quot;&gt;$REPS&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$URL&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# flags:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -b - benchmark means no gap between requests&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -c - concurrency is number of requests to make at one time&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -r - repititions is the number of times to run&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#         the same amount of concurrent requests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This executable will request &lt;code class=&quot;highlighter-rouge&quot;&gt;localhost:3000/index&lt;/code&gt; which routes to &lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller#index&lt;/code&gt; at a concurrency of 30 workers for 20 repetitions resulting in 600 total requests.&lt;/p&gt;

&lt;p&gt;Keeping this script static allows for the web server’s configuration to change and each test to be congruent with others.&lt;/p&gt;

&lt;h3 id=&quot;metrics-for-success&quot;&gt;Metrics for Success&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CPU Load Average&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CPU load average is a measurement of how busy each processor is on a server.  Basically, CPU load average can be used to determine how long a CPU is idling and waiting for something to do. These numbers are very dependent on the number of processors an application has. On a Linux or MacOS machine, you can &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt; the &lt;code class=&quot;highlighter-rouge&quot;&gt;/proc/cpuinfo&lt;/code&gt; file to get a break down of how many processors are available to you.&lt;/p&gt;

&lt;p&gt;On the machine used to test this application, 4 processors are available.  Translating that to percentage of usage, we would see a value of &lt;code class=&quot;highlighter-rouge&quot;&gt;4.0&lt;/code&gt; for our CPU load average if all processors were being completely used. Any value higher than that and we’d have work waiting to be done by a processor. Conversely, a value much lower than &lt;code class=&quot;highlighter-rouge&quot;&gt;4.0&lt;/code&gt; indicates that some processors are not doing anything.&lt;/p&gt;

&lt;p&gt;CPU load average is displayed with 3 numbers ex: &lt;code class=&quot;highlighter-rouge&quot;&gt;0.1 0.4 0.8&lt;/code&gt; which translates to &lt;code class=&quot;highlighter-rouge&quot;&gt;1 min 5 min 10 min&lt;/code&gt; averages. If the &lt;code class=&quot;highlighter-rouge&quot;&gt;1 min&lt;/code&gt; average is higher than the &lt;code class=&quot;highlighter-rouge&quot;&gt;5 min&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;10 min&lt;/code&gt; averages, server load is increasing. If the &lt;code class=&quot;highlighter-rouge&quot;&gt;1 min&lt;/code&gt; average is lower than the &lt;code class=&quot;highlighter-rouge&quot;&gt;5 min&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;10 min&lt;/code&gt; averages, server load is decreasing. The only metric reported in this summary will be the &lt;code class=&quot;highlighter-rouge&quot;&gt;1 min&lt;/code&gt; load average since it is measured while the server is under siege.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Memory Usage is the amount of memory (RAM) used by the application. When a server runs out of RAM, it creates virtual memory out of partitioned space on the disk to overflow into. This is called swapping and it can greatly reduce the efficiency of a server. Along with CPU load average, making sure a server’s memory usage is below capacity is an important way to keep a healthy and happy application.&lt;/p&gt;

&lt;p&gt;The amount of memory an application uses in total should be balanced by any other &lt;code class=&quot;highlighter-rouge&quot;&gt;processes&lt;/code&gt; running on that server while leaving some amount of room for utility applications. Using more than the memory available on a server will lead to performance issues.&lt;/p&gt;

&lt;h3 id=&quot;io-intensive-threads-v-processes-and-throughput&quot;&gt;I/O Intensive Threads v Processes and Throughput&lt;/h3&gt;

&lt;p&gt;With the metrics explained, let’s see the results of the siege on the I/O blocking application:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Processes&lt;/th&gt;
      &lt;th&gt;Threads&lt;/th&gt;
      &lt;th&gt;Duration(seconds)&lt;/th&gt;
      &lt;th&gt;Transactions/second&lt;/th&gt;
      &lt;th&gt;Memory(mb)&lt;/th&gt;
      &lt;th&gt;CPU Load&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;77.45&lt;/td&gt;
      &lt;td&gt;7.75&lt;/td&gt;
      &lt;td&gt;73&lt;/td&gt;
      &lt;td&gt;0.57&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;16.06&lt;/td&gt;
      &lt;td&gt;37.36&lt;/td&gt;
      &lt;td&gt;75&lt;/td&gt;
      &lt;td&gt;0.54&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;100&lt;/td&gt;
      &lt;td&gt;15.89&lt;/td&gt;
      &lt;td&gt;37.76&lt;/td&gt;
      &lt;td&gt;77&lt;/td&gt;
      &lt;td&gt;0.39&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;39.64&lt;/td&gt;
      &lt;td&gt;15.14&lt;/td&gt;
      &lt;td&gt;136&lt;/td&gt;
      &lt;td&gt;0.52&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;8.14&lt;/td&gt;
      &lt;td&gt;73.71&lt;/td&gt;
      &lt;td&gt;146&lt;/td&gt;
      &lt;td&gt;0.78&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;8.16&lt;/td&gt;
      &lt;td&gt;73.53&lt;/td&gt;
      &lt;td&gt;680&lt;/td&gt;
      &lt;td&gt;0.79&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;3.89&lt;/td&gt;
      &lt;td&gt;154.24&lt;/td&gt;
      &lt;td&gt;715&lt;/td&gt;
      &lt;td&gt;0.54&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For the example I/O bound application, CPU load average never rises above &lt;code class=&quot;highlighter-rouge&quot;&gt;1.0&lt;/code&gt; regardless of &lt;code class=&quot;highlighter-rouge&quot;&gt;Process&lt;/code&gt; count. This means that the server is not using its processing power to its full potential because the requests do not demand it.&lt;/p&gt;

&lt;p&gt;On the other hand, the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; makes a big difference for I/O blocking operations.  With a single &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt;, it takes 77 seconds to complete all 600 requests. Just increasing that number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; to 10 makes the same work take 16 seconds!  But look at what happens when &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; are increased to 100: the same jump in throughput doesn’t happen. This shows that the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; an application can utilize has an upper limit .&lt;/p&gt;

&lt;p&gt;Additionally, the memory usage quickly increases with the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;processes&lt;/code&gt; on the machine. For a very simple application like this with no database, the maximum memory usage of 715mb isn’t huge but on a traditional Rails application, &lt;em&gt;each&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;process&lt;/code&gt; could easily have a few hundred mb of memory usage. Along with hard caps for database connections, maintaining too many &lt;code class=&quot;highlighter-rouge&quot;&gt;processes&lt;/code&gt; can quickly use more memory than a server has available.&lt;/p&gt;

&lt;p&gt;Similar to &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;, infinitely scaling &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; is not a sure way to get the best results. In this example, a balance of 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; and 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; gives the best throughput at nearly a 700% memory increase.&lt;/p&gt;

&lt;h2 id=&quot;cpu-intensive-application&quot;&gt;CPU Intensive Application&lt;/h2&gt;

&lt;p&gt;To see how the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; impact a more CPU intensive application the &lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller&lt;/code&gt; has been changed:&lt;/p&gt;

&lt;h3 id=&quot;indexcontrollerrb-1&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller.rb&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IndexController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tax_cpu&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;hello: :there&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tax_cpu&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now each request will create an array of &lt;code class=&quot;highlighter-rouge&quot;&gt;100,000&lt;/code&gt; integers and sort them.&lt;/p&gt;

&lt;p&gt;The same siege command is run against the same &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Process&lt;/code&gt; configuration counts.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Processes&lt;/th&gt;
      &lt;th&gt;Threads&lt;/th&gt;
      &lt;th&gt;Duration(seconds)&lt;/th&gt;
      &lt;th&gt;Transactions/second&lt;/th&gt;
      &lt;th&gt;Memory(mb)&lt;/th&gt;
      &lt;th&gt;CPU Load&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;18.34&lt;/td&gt;
      &lt;td&gt;32.72&lt;/td&gt;
      &lt;td&gt;114&lt;/td&gt;
      &lt;td&gt;0.64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;18.16&lt;/td&gt;
      &lt;td&gt;33.04&lt;/td&gt;
      &lt;td&gt;134&lt;/td&gt;
      &lt;td&gt;0.79&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;100&lt;/td&gt;
      &lt;td&gt;18.45&lt;/td&gt;
      &lt;td&gt;32.52&lt;/td&gt;
      &lt;td&gt;184&lt;/td&gt;
      &lt;td&gt;1.05&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;10.26&lt;/td&gt;
      &lt;td&gt;58.48&lt;/td&gt;
      &lt;td&gt;230&lt;/td&gt;
      &lt;td&gt;1.12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;11.73&lt;/td&gt;
      &lt;td&gt;51.15&lt;/td&gt;
      &lt;td&gt;270&lt;/td&gt;
      &lt;td&gt;0.89&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;8.73&lt;/td&gt;
      &lt;td&gt;68.73&lt;/td&gt;
      &lt;td&gt;1040&lt;/td&gt;
      &lt;td&gt;2.13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;8.95&lt;/td&gt;
      &lt;td&gt;67.04&lt;/td&gt;
      &lt;td&gt;1180&lt;/td&gt;
      &lt;td&gt;2.65&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;cpu-intensive-threads-v-processes-and-throughput&quot;&gt;CPU Intensive Threads v Processes and Throughput&lt;/h3&gt;

&lt;p&gt;For the CPU intensive code, only increasing &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; does nothing for overall execution time. The 600 requests require around 18 seconds no with 1 &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; and with 100 &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, doubling the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; cuts execution time by almost half! However, increasing the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; from 2 to 10 (a 500% increase) does not decrease the execution time by another 500%.  Just like in the I/O bound application, scaling &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; will eventually experience diminishing returns, making each additional &lt;code class=&quot;highlighter-rouge&quot;&gt;process&lt;/code&gt; less valuable.&lt;/p&gt;

&lt;p&gt;During the CPU intensive code testing, the server never experienced a fully saturated load average of &lt;code class=&quot;highlighter-rouge&quot;&gt;4.0&lt;/code&gt;. This is because the example code was not all that taxing. In a real application serving end users, it is surprisingly easy to make full use of all CPU resources with enough &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;a-little-realism&quot;&gt;A Little Realism&lt;/h2&gt;

&lt;p&gt;In the real world, an application is not likely to be only CPU or I/O intensive but rather some mixture of both. To help add a little bit of variety to this test, the two operations are combined and run at a percentage:&lt;/p&gt;

&lt;h3 id=&quot;indexcontrollerrb-2&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller.rb&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IndexController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tax_cpu&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;interval_sleep&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;hello: :there&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tax_cpu&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;interval_sleep&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now this controller will be I/O bound approximately 66% of the time and CPU bound the other 33%.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: While more realistic, this application is not a perfect representation of any real request structure out there and every individual app should be evaluated on its own.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Running the same siege command a final time on this application yields:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Processes&lt;/th&gt;
      &lt;th&gt;Threads&lt;/th&gt;
      &lt;th&gt;Duration(seconds)&lt;/th&gt;
      &lt;th&gt;Transactions/second&lt;/th&gt;
      &lt;th&gt;Memory(mb)&lt;/th&gt;
      &lt;th&gt;CPU Load&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;61.40&lt;/td&gt;
      &lt;td&gt;9.7&lt;/td&gt;
      &lt;td&gt;86&lt;/td&gt;
      &lt;td&gt;0.65&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;14.28&lt;/td&gt;
      &lt;td&gt;42.02&lt;/td&gt;
      &lt;td&gt;111&lt;/td&gt;
      &lt;td&gt;0.58&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;100&lt;/td&gt;
      &lt;td&gt;14.03&lt;/td&gt;
      &lt;td&gt;42.77&lt;/td&gt;
      &lt;td&gt;167&lt;/td&gt;
      &lt;td&gt;1.31&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;30.24&lt;/td&gt;
      &lt;td&gt;19.84&lt;/td&gt;
      &lt;td&gt;174&lt;/td&gt;
      &lt;td&gt;0.91&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;6.97&lt;/td&gt;
      &lt;td&gt;86.08&lt;/td&gt;
      &lt;td&gt;206&lt;/td&gt;
      &lt;td&gt;0.93&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;6.74&lt;/td&gt;
      &lt;td&gt;89.02&lt;/td&gt;
      &lt;td&gt;790&lt;/td&gt;
      &lt;td&gt;0.79&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;4.44&lt;/td&gt;
      &lt;td&gt;135.14&lt;/td&gt;
      &lt;td&gt;960&lt;/td&gt;
      &lt;td&gt;1.43&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; each have an impact in these results.  Unlike the other versions of &lt;code class=&quot;highlighter-rouge&quot;&gt;index_controller.rb&lt;/code&gt;, if too few &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; are allocated, the application will wait on I/O operations. Likewise, too few &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; tie up the CPU, blocking other requests from being served.&lt;/p&gt;

&lt;p&gt;While the fastest possible results is 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; and 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;, it is important to look at the load average and memory usage. For nearly 1/5th the memory, 2 &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; and 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; accomplishes the task in only 2 more seconds. A server that has memory issues or an application that is memory starved might adopt this more modest configuration to save memory. The 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt;, 10 &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; configuration also has the highest CPU load average. Just like memory concerns, a server with lower processing power might be better &lt;em&gt;served&lt;/em&gt; with fewer &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; competing for CPU time.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;The number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; can be the deciding factor on a web application’s performance. Additionally, understanding how the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Procesess&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; impact a server is useful for choosing and configuring a web server. Any code which uses concurrency can benefit from this knowledge. Balancing memory usage, external resource connection limits, and CPU load average is a great way to make sure a server is provisioned correctly and might even save some money.&lt;/p&gt;

&lt;p&gt;When evaluating the best configuration for your web server, this simple list is a great starting point:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use only the available memory for the server.&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; for blocking code and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; for CPU intensive code.&lt;/li&gt;
  &lt;li&gt;Use tools like &lt;code class=&quot;highlighter-rouge&quot;&gt;siege&lt;/code&gt; for benchmarking and testing different configurations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Things like &lt;code class=&quot;highlighter-rouge&quot;&gt;thread&lt;/code&gt; starvation, semaphores, &lt;code class=&quot;highlighter-rouge&quot;&gt;thread&lt;/code&gt; pooling and other concerns regarding concurrent programming were intentionally not mentioned in this post.  Understanding how &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt; work at a high level can enable the configuration and choice of web server, but if you want to write your own complex concurrent Ruby code, I’d suggest &lt;a href=&quot;https://github.com/ruby-concurrency/concurrent-ruby&quot;&gt;concurrent-ruby&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Improving Remote Work as a Software Engineer</title>
   <link href="https://jakeyesbeck.com/2018/02/18/improving-remote-work-as-a-software-engineer/"/>
   <updated>2018-02-18T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2018/02/18/improving-remote-work-as-a-software-engineer</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/remote_working.jpg&quot; alt=&quot;Remote Working&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After working in the Bay Area for many years, I decided that being able to
afford a house was something I’d like to do. That and family led me back to the East
Coast and a new chapter of my career began: Remote Software Engineering.&lt;/p&gt;

&lt;p&gt;Transitioning to working remotely in any profession has its challenges. After
a few years as a remote software engineer, I have learned many things that don’t work
and a few that do. Most of the things that didn’t work helped point me in the
direction to those that do and hopefully these bits of insight can help others.
These tips are most relevant to someone who is the only or one of few remote
engineers on their team.&lt;/p&gt;

&lt;h2 id=&quot;presence&quot;&gt;Presence&lt;/h2&gt;

&lt;p&gt;The largest and most obvious challenge one will face as a remote software
engineer is a lack of presence. In an office, people can have small side
conversations, ask about one another’s weekends, or simply say “hello” in the
hallway. While seemingly inconsequential, these tiny interactions establish presence.&lt;/p&gt;

&lt;p&gt;Maintaining presence is important if an engineer is a member of a team or has
many stakeholders in their work. Presence can make the difference between being
perceived as &lt;em&gt;“a member of team”&lt;/em&gt; as opposed to &lt;em&gt;“that one person who works on…
What is it they do again?”&lt;/em&gt;. The former helps a person feel unified with the team they work for,
the mission they are striving towards, and the product they are building; the
latter is hollow and temporary.&lt;/p&gt;

&lt;p&gt;So how does a remote software engineer maintain presence? With consistent yet
relevant communication. Whether a company uses Hipchat, Slack, Google Hangouts, or
another chat application, instant communication should already be baked into an
organization’s workflow and can be utilized to establish presence. While
over-communication is rarely valuable, sending short and well constructed
messages about current progress or next steps helps keep team members informed and
questions answered.&lt;/p&gt;

&lt;p&gt;If instant messaging isn’t on the menu, status emails might do well in its place.
There is nothing worse than an employer, manager, or team lead thinking that a remote
software engineer isn’t delivering what they should. A single daily email can help
provide visibility. The email doesn’t need to be very verbose. It can be as simple as
a list of what’s been done today, any blockers that have been encountered, or an update
to a nearing deadline. It might seem tedious or unnecessary but, to a
manager or stakeholder, such an email can help reassure them of progress and
collaboration.&lt;/p&gt;

&lt;h2 id=&quot;tone&quot;&gt;Tone&lt;/h2&gt;

&lt;p&gt;Since communication is so important for a remote software engineer, the tone in
which that communication is even more important. &lt;em&gt;Tone is incredibly hard to convey
over text communication&lt;/em&gt;. Because of this, it might take a few tries to accurately
convey negative messages without sounding like an extremely irritated or otherwise
nasty individual.&lt;/p&gt;

&lt;p&gt;Code reviews are a great example of how the right tone can make all the
difference. Think of code reviews in the recent past, unless a team goes out of their way to be super
positive, most code review comments are a little negative. For example, a typical code
review might have comments like: &lt;em&gt;“This doesn’t look right”&lt;/em&gt;, _“Change &lt;x&gt; to &lt;y&gt;
here&quot;_, or _&quot;I don&#39;t agree with this&quot;_. The reason these comments are not an
issue for a local team is because this is not the only comments they exchange.
Perhaps a local team will have one-off side conversations where they explain their
opinions in a more positive way. Or, completely separate to the code review, a local
team shares some amount of small talk that is likely positive. Whatever the case,
the local team has a mixture of positive interactions along with (most likely) negative
code review comments. The remote software engineer does not have this luxury. All
they have to offer is their code review comments which, most likely, are not
filled with a very positive tone. This is what must be adjusted.&lt;/y&gt;&lt;/x&gt;&lt;/p&gt;

&lt;p&gt;Utilizing a positive tone in code reviews and other communication help remind
people that their remote team member is just that: a valuable member of the
team, invested in their work and the happiness of their colleagues. To enable
this perception, the remote software engineer can find opportunities for positivity
that might be easily overlooked. Simple comments on how a method’s signature is nicely
defined or a code comment is especially helpful are easy things to point out during
a code review that express positivity.&lt;/p&gt;

&lt;h2 id=&quot;availability&quot;&gt;Availability&lt;/h2&gt;

&lt;p&gt;For those remote software engineers in the same timezone as the rest of their team,
availability shouldn’t be an issue. For everyone else, there may be times
in which “after hours” communication can help boost one’s reputation as being
dependable and invested despite being remote.&lt;/p&gt;

&lt;p&gt;Responding in off hours is not the same as being always available. People need and
benefit from downtime and the remote engineer is no different.  Because of this,
the availability of a remote employee should be flexible but not unreasonable.
Responding to a few emails or chat messages after hours or during a morning coffee
before their “normal work day” can go a long way.  After all, if a company is willing
to be flexible and work with a remote software engineer, shouldn’t that engineer also
be flexible?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A Few RSpec Helpful Hints</title>
   <link href="https://jakeyesbeck.com/2017/07/12/a-few-rspec-helpful-hints/"/>
   <updated>2017-07-12T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2017/07/12/a-few-rspec-helpful-hints</id>
   <content type="html">&lt;p&gt;Two main frameworks dominate the Ruby testing world: Rspec and MiniTest. RSpec
is a very expressive testing framework with many great features and helpers to
make tests readable. When writing RSpec tests, here are just a few not so
obvious hints that could make tests even easier to write, read, and maintain.&lt;/p&gt;

&lt;p&gt;Assuming a system exists with &lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Authors&lt;/code&gt;, let’s utilize these hints
to make testing easy.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:genre&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@genre&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genre&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;has_written_a_book?&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;subject-and--let-variables&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;subject&lt;/code&gt; and  &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt; Variables&lt;/h2&gt;

&lt;p&gt;A great way to keep specs DRY and readable are via &lt;code class=&quot;highlighter-rouge&quot;&gt;subject&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt; variable
declarations.&lt;/p&gt;

&lt;p&gt;For example, if we want to assert an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; has a &lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt;, a test without &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt;
and &lt;code class=&quot;highlighter-rouge&quot;&gt;subject&lt;/code&gt; variables might look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@book_genre&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Historical Fiction&#39;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@book_title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Tale of Two Cities&#39;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@author_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Charles Dickens&#39;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@author_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#name&#39;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;has a name set&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@author_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;While correct, additional tests asserting number of books, a different name, or
other things about this &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; could become very verbose.&lt;/p&gt;

&lt;p&gt;Instead, we can introduce &lt;code class=&quot;highlighter-rouge&quot;&gt;subject&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt; variables to keep things DRY and
reusable:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Historical Fiction&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Tale of Two Cities&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Charles Dickens&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#name&#39;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;has a name set&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#books&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;with books&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;has books set&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;without books&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;books variable is nil&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sets books to an empty array&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;books variable is an empty array&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sets books to an empty array&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Instead of needing multiple &lt;code class=&quot;highlighter-rouge&quot;&gt;before&lt;/code&gt; blocks to set and reset instance variables,
this code utilizing &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt; variables is concise and easy to read. More specifically,
the way these tests work is: each time an &lt;code class=&quot;highlighter-rouge&quot;&gt;it&lt;/code&gt; block is run, the &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt; variables
within the nearest &lt;code class=&quot;highlighter-rouge&quot;&gt;context&lt;/code&gt; are used to initialize the &lt;code class=&quot;highlighter-rouge&quot;&gt;subject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By setting important &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt; variables, a context that tests if &lt;code class=&quot;highlighter-rouge&quot;&gt;subject.books&lt;/code&gt; is
an array based on an input of &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;[]&lt;/code&gt; is as simple as changing the &lt;code class=&quot;highlighter-rouge&quot;&gt;let&lt;/code&gt;
definition: &lt;code class=&quot;highlighter-rouge&quot;&gt;let(:book_array) { nil }&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;loose-expectations&quot;&gt;Loose Expectations&lt;/h2&gt;

&lt;p&gt;When a test does not care about specifics, &lt;code class=&quot;highlighter-rouge&quot;&gt;RSpec&lt;/code&gt; allows the use of general
expectations and placeholders. These placeholders can help mitigate a test’s
complexity by only focusing on what is truly important.&lt;/p&gt;

&lt;h3 id=&quot;anything&quot;&gt;1. &lt;code class=&quot;highlighter-rouge&quot;&gt;anything&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Just like it sounds, the &lt;code class=&quot;highlighter-rouge&quot;&gt;anything&lt;/code&gt; argument matcher can be used when a method
requires an argument but the specifics do not matter for the test.&lt;/p&gt;

&lt;p&gt;If an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; test wants to assert that a &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; has been written, but doesn’t
care about the &lt;code class=&quot;highlighter-rouge&quot;&gt;title&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;genre&lt;/code&gt; of the book, &lt;code class=&quot;highlighter-rouge&quot;&gt;anything&lt;/code&gt; can be used:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#has_written_a_book?&#39; do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;when books are passed in&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anything&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anything&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;is true&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;has_written_a_book?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;hashincluding&quot;&gt;2. &lt;code class=&quot;highlighter-rouge&quot;&gt;hash_including&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;When testing a method that expects a &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt;, some elements of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt; may be more
important than others. The &lt;code class=&quot;highlighter-rouge&quot;&gt;hash_including&lt;/code&gt; matcher allows a developer to assert one
or many key/value pairs within a hash without needing to specify the entire hash.&lt;/p&gt;

&lt;p&gt;Assuming the &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; class has a method which instantiates a new HTTP client (for
fetching additional information), it might look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_information&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;HTTPClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;genre: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;time: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/information&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The test for this method should assert that the client is initialized with a few
crucial pieces. The &lt;code class=&quot;highlighter-rouge&quot;&gt;hash_including&lt;/code&gt; argument matcher works nicely here.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#fetch_information&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Historical Fiction&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Tale of Two Cities&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;instantiates the client correctly&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTPClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash_including&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                             &lt;span class=&quot;ss&quot;&gt;genre: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch_information&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The versatile &lt;code class=&quot;highlighter-rouge&quot;&gt;hash_including&lt;/code&gt; argument matcher can specify key/value pairs of an
expected hash or just keys. Here, the test only care that the &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;title&lt;/code&gt;
and &lt;code class=&quot;highlighter-rouge&quot;&gt;genre&lt;/code&gt; are passed along.&lt;/p&gt;

&lt;h3 id=&quot;matcharray&quot;&gt;3. &lt;code class=&quot;highlighter-rouge&quot;&gt;match_array&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;In Ruby, two &lt;code class=&quot;highlighter-rouge&quot;&gt;Arrays&lt;/code&gt; are equal if and only if they contain the same elements in
the same order. In some tests, this strict equality criteria might not always
be necessary. For those cases, RSpec provides a &lt;code class=&quot;highlighter-rouge&quot;&gt;match_array&lt;/code&gt; matcher to
make tests less brittle.&lt;/p&gt;

&lt;p&gt;If the &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; class retrieved its list of &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; from a database, the order
of &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; might not be consistent due to default scopes or when records are
updated.&lt;/p&gt;

&lt;p&gt;Given a &lt;code class=&quot;highlighter-rouge&quot;&gt;fetch_books&lt;/code&gt; method that looks something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_books&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;BookDB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;author_name: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Utilizing &lt;code class=&quot;highlighter-rouge&quot;&gt;match_array&lt;/code&gt;, a test can assert that the proper &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; are returned
regardless of order:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#fetch_books&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Jane Austen&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;BookDB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create_book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;author_name: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;fetches the books correctly&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch_books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;verifying-doubles&quot;&gt;Verifying Doubles&lt;/h2&gt;

&lt;p&gt;Mocking in RSpec is a simple way to ensure code that is expected to run, has
indeed done so.&lt;/p&gt;

&lt;p&gt;To fetch reviews for a &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;, a third party API is used. The unit test
surrounding that functionality should not actually call out to that API.
Instead, a test should assert that the proper request is made.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ..&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reviews&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SUPER_SECRET_API_KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;reviews/?title=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;amp;genre=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genre&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;One way to test this code would be to write a stubbing method and return some
test data:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Historical Fiction&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Tale of Two Cities&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#reviews&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:fake_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;critic: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Pat M.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;stars: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;comments: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Great Read!&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;critic: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Sanjay R.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;stars: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;comments: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Interesting!&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;critic: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Rupa T.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;stars: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;comments: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;It was nice!&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:test_api_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TEST_API_KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_api_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_api_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;fetches them from the API&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will work as long as the &lt;code class=&quot;highlighter-rouge&quot;&gt;Review::API&lt;/code&gt; contract does not change how it
fetches reviews. However, if the method does change for some reason, this code
will pass and the application will fail in production.&lt;/p&gt;

&lt;p&gt;Instead, an &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_double&lt;/code&gt; can be used to assert that a specific method is
called while still returning test data:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Historical Fiction&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Tale of Two Cities&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book_genre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#reviews&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:fake_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;critic: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Pat M.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;stars: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;comments: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Great Read!&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;critic: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Sanjay R.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;stars: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;comments: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Interesting!&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;critic: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Rupa T.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;stars: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;comments: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;It was nice!&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:test_api_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;instance_double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;get: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_api_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;fetches them from the API&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In one line, &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_double(Review::API, get: fake_reviews)&lt;/code&gt;, the client
class has been instantiated as an verifying double and the method &lt;code class=&quot;highlighter-rouge&quot;&gt;get&lt;/code&gt; has
been stubbed to return &lt;code class=&quot;highlighter-rouge&quot;&gt;fake_reviews&lt;/code&gt;. The final important piece is:
&lt;code class=&quot;highlighter-rouge&quot;&gt;allow(Review::API).to receive(:new).and_return(test_api_client)&lt;/code&gt; which tells
the class &lt;code class=&quot;highlighter-rouge&quot;&gt;Review::API&lt;/code&gt; to use the double instead a new instance when calling
&lt;code class=&quot;highlighter-rouge&quot;&gt;new&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, if the &lt;code class=&quot;highlighter-rouge&quot;&gt;Review::API&lt;/code&gt; instance method for fetching reviews changes the
test will break, throwing a &lt;code class=&quot;highlighter-rouge&quot;&gt;NoMethodError&lt;/code&gt; and hopefully saving a lot of
debugging time.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>A Successful Year of Commits</title>
   <link href="https://jakeyesbeck.com/2016/04/26/a-successful-year-of-commits/"/>
   <updated>2016-04-26T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/04/26/a-successful-year-of-commits</id>
   <content type="html">&lt;p&gt;At Rails Conf 2015, I met a lot of great people from the Ruby community. These people had a profound effect on me, instilling in me a new motivation to become part of something larger than myself. A year ago today, I embarked on a journey to better myself as a Software Engineer. &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;I decided to commit to open source software every day for a year&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even though open source software has been around for decades, up until a year ago I had thought it mostly magic and far beyond my reach. After Rails Conf 2015, it became clear to me that contributing to and becoming part of the open source community was not so far fetched.&lt;/p&gt;

&lt;h2 id=&quot;the-plan&quot;&gt;The Plan&lt;/h2&gt;

&lt;p&gt;The word “plan” might be a bit generous for what I decided to do. I was going to “just keep doing commits for a year”. Surely doing something over and over again will yield good results…right? It has to have at least &lt;em&gt;some&lt;/em&gt; effect on &lt;em&gt;some&lt;/em&gt; aspect of my programming ability.&lt;/p&gt;

&lt;p&gt;And so that is what I did. For one year, I made at least one commit to an open source repository (someone else’s or my own) every day:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/complete_year_of_commits_graph.png&quot; alt=&quot;Completed Year of Commits Github Graph&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I started this endeavor on April 26th 2015 and ended it today, April 26 2016.&lt;/p&gt;

&lt;h2 id=&quot;reality-check&quot;&gt;Reality Check&lt;/h2&gt;

&lt;p&gt;At the beginning of the year, I was under the impression that I was going to be able to contribute to other people’s repositories every day without too much effort. That idea was soon shattered due to the short time constraints I had to work with. After all, I am happily employed and unable to devote more than a few hours a day to open source work. Exploring someone else’s code base, reproducing an issue and finding a solution can take more than a few hours.&lt;/p&gt;

&lt;p&gt;It became clear that I needed to fill in gaps of time with my own projects. This ended up being much more fun than I had anticipated and I got to build some cool libraries that people would actually use:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yez/passages&quot;&gt;Passages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yez/validates_type&quot;&gt;validates_type&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yez/rescue_groups&quot;&gt;Rescue Groups&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yez/validates_subset&quot;&gt;validates_subset&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yez/honest_renter&quot;&gt;Honest Renter&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, this does not mean that my only contributions were to my own projects. Oh no, far from it, I forked repositories on Github like crazy and ended up contributing to a lot of great projects:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/codetriage/codetriage&quot;&gt;Code Triage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Growstuff/growstuff&quot;&gt;Growstuff&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sendgrid/sendgrid-ruby&quot;&gt;SendGrid Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/girishso/pluck_to_hash&quot;&gt;Pluck to Hash&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/covermymeds/fetching-gem&quot;&gt;Fetching&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/codegram/date_validator&quot;&gt;Date Validator&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;…and many more&lt;/p&gt;

&lt;p&gt;Each of these projects taught me something new and introduced me to many different coding styles. My contributions ranged from one-liners to entire spec suite creations. If any maintainers of these libraries end up reading this post: Thank you for all the work you do. Open source development is done for free and I value the time you put into it.&lt;/p&gt;

&lt;h2 id=&quot;expect-the-unexpected&quot;&gt;Expect the Unexpected&lt;/h2&gt;

&lt;p&gt;A delightful surprise during this project was writing this blog. I had a feeling that I would enjoy writing every week and originally intended to only write about the Year of Commits project. However, a few weeks into the posts and I quickly found new inspiration. It turns out that people actually like reading my explanations of coding patterns, designs, and tutorials:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;
  &lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/jakeyesbeck&quot;&gt;@jakeyesbeck&lt;/a&gt; Hey man! Your blog is awesome! Keep going! Also thanks for sharing your thoughts and learned things! 👍&lt;/p&gt;&amp;mdash; Gabriel Francisco (@fgbreel) &lt;a href=&quot;https://twitter.com/fgbreel/status/700493892861485056&quot;&gt;February 19, 2016&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;
  &lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Been really impressed with &lt;a href=&quot;https://twitter.com/jakeyesbeck&quot;&gt;@jakeyesbeck&lt;/a&gt;&amp;#39;s blog recently for great &lt;a href=&quot;https://twitter.com/hashtag/Ruby?src=hash&quot;&gt;#Ruby&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/hashtag/RubyOnRails?src=hash&quot;&gt;#RubyOnRails&lt;/a&gt; posts. Check it out! &lt;a href=&quot;https://t.co/cIGGTdzqlL&quot;&gt;https://t.co/cIGGTdzqlL&lt;/a&gt;&lt;/p&gt;&amp;mdash; Brad Urani (@bradurani) &lt;a href=&quot;https://twitter.com/bradurani/status/701544221224755200&quot;&gt;February 21, 2016&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;Of course, not all feedback on my posts was positive, but all of it was useful. Having my opinion out there, my content distributed and consumed has been extremely motivating and completely unexpected. Finding topics I thought would be useful and interesting to others was always a hard challenge, but having a self-imposed obligation of one post per week kept me honest.&lt;/p&gt;

&lt;p&gt;I now believe all software engineers should write. There are a lot of parallels between writing code and writing paragraphs; both are done with great care. Writing about something is a great way to express your ideas, share knowledge, and solidify concepts for yourself. Aside from the growth in my technical skills during this past year, having my writing appreciated made all my hard work worth it.&lt;/p&gt;

&lt;p&gt;I was lucky enough to be &lt;a href=&quot;https://rubyweekly.com/issues/284&quot;&gt;featured in Ruby Weekly&lt;/a&gt; a &lt;a href=&quot;https://rubyweekly.com/issues/285&quot;&gt;few times&lt;/a&gt; and was even mentioned in a couple podcasts.&lt;/p&gt;

&lt;p&gt;This support completely validated my commitment and helped make this project so productive.&lt;/p&gt;

&lt;h2 id=&quot;what-i-learned&quot;&gt;What I Learned&lt;/h2&gt;

&lt;p&gt;The big question that most people I talk about this project ask is: “What have I learned while doing it?” Early on in the year, I would answer by explaining some new software pattern or Ruby library that I came across. But, after a few months, I realised something much more important: &lt;em&gt;the value of perseverance&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Committing code every day for a week is not difficult. Writing software every day for a month is a little harder, and every day for a year is harder still. Within a year’s time, inconveniences are bound to appear. Be it an unexpected spell of food poisoning, an impromptu vacation to Las Vegas, or a simple release of a new Netflix show to binge watch, the coding must continue. All of these things did indeed happen to me over the course of a year and it was very tempting to say to myself: “What is the harm in missing one day?”&lt;/p&gt;

&lt;p&gt;But one missed day meant more and more as time went on. At 100 consecutive days, missing one day would have been disappointing, at 200 days it would have been devastating and at 300 days, it was unthinkable. When people did not seem to care about libraries I worked on or blog posts I published, it was easier to think about skipping a day.&lt;/p&gt;

&lt;p&gt;And here, a year later, I stand without missing a single day. Persevering through criticism and rejection, I kept going until my task was done. If a blog post was not well received, I had next week to try again. If a library was not found useful, I could tweak it until it was. Perseverance was my hammer and everything started to look like a nail.&lt;/p&gt;

&lt;p&gt;And it worked. I learned a lot, met some great people, and hopefully helped a few people along the way. Believing in myself and my ability to persevere was my biggest lesson during this project and I will not soon forget it.&lt;/p&gt;

&lt;h2 id=&quot;would-i-do-it-again&quot;&gt;Would I do it Again?&lt;/h2&gt;

&lt;p&gt;In short, heck yes I would. This experience has been one of the most beneficial, positive, and growth inducing tasks I have ever done. Thinking back to a year ago, my attitude towards open source software and my own abilities as a software engineer have completely changed. Working with many different types of people and receiving a variety of feedback has been a very eye opening experience.&lt;/p&gt;

&lt;p&gt;Too often in our daily lives are we subject to repetition. These patterns can be confining while not appearing as such. Breaking out of one’s routine and exposing yourself to a variety of new stimuli can help maintain an open mind about new ideas or technology.&lt;/p&gt;

&lt;p&gt;This project is not for everyone. I was lucky enough to have the time and energy to complete a task of this scale and for that I am supremely thankful.&lt;/p&gt;

&lt;h2 id=&quot;looking-forward&quot;&gt;Looking Forward&lt;/h2&gt;

&lt;p&gt;I plan to keep writing and contributing to open source projects as frequently as time allows. I doubt I will ever obtain the same level of Github streak that this project allotted me, but I hope to continue to make meaningful contributions to open source projects.&lt;/p&gt;

&lt;p&gt;The confidence and exposure to many different types of codebases is something that I will value for a long time. I am more than thankful for all the people who said kind things to me or gave me words of encouragement. Without those people, there is no way that I could have accomplished this.&lt;/p&gt;

&lt;p&gt;Thank you all so much, now I think its time for me to take a little break. I plan to be back in a few weeks, refreshed and ready to write more.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Diagnose Ruby on Rails N + 1 Query Problems</title>
   <link href="https://jakeyesbeck.com/2016/04/17/how-to-diagnose-ruby-on-rails-n-plus-1-query-problems/"/>
   <updated>2016-04-17T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/04/17/how-to-diagnose-ruby-on-rails-n-plus-1-query-problems</id>
   <content type="html">&lt;p&gt;Diagnosing performance problems in a production Ruby on Rails application can be deceptively complex. When constructing a new application or expanding the features of an existing one, development environments that are not subject to typical production web traffic may not make performance issues evident. In those instances, the use of some simple (and mostly free) tools can help diagnose performance issues in production.&lt;/p&gt;

&lt;p&gt;If an application is hosted on Heroku, the New Relic add-on can be added to the application for free. Despite it having a few limitations, the free version of New Relic can be extremely valuable for diagnosing some common performance issues.&lt;/p&gt;

&lt;p&gt;New Relic will be the primary tool used in this post for analysis, but an application’s log files can prove to be just as valuable when analyzed correctly.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;The example application has the following database structure and respective models:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:last_name&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:posts&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:theme_id&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:themes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:posts&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:theme&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Theme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;An example controller, &lt;code class=&quot;highlighter-rouge&quot;&gt;home_controller.rb&lt;/code&gt; has a single action:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HomeController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The above action renders a single simple view, &lt;code class=&quot;highlighter-rouge&quot;&gt;show.html.haml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;%h3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Posts from &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first_name&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;last_name&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Theme &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Additionally in the application’s &lt;code class=&quot;highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;, the New Relic Ruby gem has been added:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;https://rubygems.org&#39;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;newrelic_rpm&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;On a development machine under no contention, this action will quickly render a page consisting of a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&#39;s&lt;/code&gt; name information, a list of their &lt;code class=&quot;highlighter-rouge&quot;&gt;posts&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;theme&lt;/code&gt; each post belongs to.&lt;/p&gt;

&lt;p&gt;However, there is an &lt;code class=&quot;highlighter-rouge&quot;&gt;N + 1&lt;/code&gt; query issue with this code. In a development environment, this issue might be overlooked or deemed satisfactory. It may not be until this code is released into the wild that a problem is seen.&lt;/p&gt;

&lt;h2 id=&quot;the-n--1-problem&quot;&gt;The N + 1 Problem&lt;/h2&gt;

&lt;p&gt;An &lt;code class=&quot;highlighter-rouge&quot;&gt;N + 1&lt;/code&gt; query problem is responsible for an application’s execution of far more queries than needed. The &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;N + 1&lt;/code&gt; refers to first query executed, in this case when loading: &lt;code class=&quot;highlighter-rouge&quot;&gt;@user.posts&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;N&lt;/code&gt; then refers to number of queries that must be executed when traversing over the list of elements, in this case each &lt;code class=&quot;highlighter-rouge&quot;&gt;post&#39;s&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;theme&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As with most problems, the first step to solving them involves validating their existence. This is the step in which New Relic is utilized.&lt;/p&gt;

&lt;p&gt;When using Heroku, after the New Relic add-on has been created for an application, it can be opened with:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;heroku addons:open newrelic --app my-application-name
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Otherwise, a user can simply Log-in at &lt;code class=&quot;highlighter-rouge&quot;&gt;rpm.newrelic.com&lt;/code&gt; and navigate to their application after signing up and linking their application.&lt;/p&gt;

&lt;p&gt;Once the desired application has been opened in New Relic, navigating to the the &lt;code class=&quot;highlighter-rouge&quot;&gt;transactions&lt;/code&gt; tab and then the &lt;code class=&quot;highlighter-rouge&quot;&gt;HomeController#show&lt;/code&gt; transaction will show our &lt;code class=&quot;highlighter-rouge&quot;&gt;N + 1&lt;/code&gt; issue.&lt;/p&gt;

&lt;p&gt;At first glance, the graph of this simple endpoint is telling a alarming story. A large amount of time is spent in the database, fetching records necessary to render the page:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/graph_before_fix.png&quot; alt=&quot;New Relic Transaction Trace Graph for N + 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Below this graph, New Relic conveniently displays the call count breakdown for this transaction:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/call_count_table_before_fix.png&quot; alt=&quot;New Relic Transaction Call Count Table for N + 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Immediately, we can see that the &lt;code class=&quot;highlighter-rouge&quot;&gt;Postgres Theme find&lt;/code&gt; is called an average of &lt;strong&gt;20&lt;/strong&gt; times per transaction. Compared to the single call count of the surrounding methods in this table, &lt;strong&gt;20&lt;/strong&gt; seems excessive.&lt;/p&gt;

&lt;h2 id=&quot;investigation-station&quot;&gt;Investigation Station&lt;/h2&gt;

&lt;p&gt;With a direction to run in, it is time to revisit the code and find the offending line. Luckily, this application’s code line count totals to about 40, so the search is short.&lt;/p&gt;

&lt;p&gt;Here is the line that causes the issue:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;.theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Theme &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Each time &lt;code class=&quot;highlighter-rouge&quot;&gt;post.theme.name&lt;/code&gt; is called the following query is executed:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;&quot;themes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;themes&quot;&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;themes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;id&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LIMIT&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;While things like query caching, primary key indexes and other performance aiding features exist within production relational databases, issuing the same query 20 times per page load is still wasteful.&lt;/p&gt;

&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;/h2&gt;

&lt;p&gt;Many solutions to this problem exist, each with their own pros and cons. The important part of this post is how to effectively use New Relic to diagnose a problem in a production Ruby on Rails application.&lt;/p&gt;

&lt;p&gt;All that aside, what kind of effect does a solution to this problem have on our example application?&lt;/p&gt;

&lt;p&gt;To rid this system of its &lt;code class=&quot;highlighter-rouge&quot;&gt;N + 1&lt;/code&gt; query, we can prepend some information to the simple &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; method, letting &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; do the work for us:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HomeController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eager_load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;posts: :theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here the &lt;code class=&quot;highlighter-rouge&quot;&gt;eager_load&lt;/code&gt; method will use the established foreign keys via the &lt;code class=&quot;highlighter-rouge&quot;&gt;belongs_to&lt;/code&gt; relationships and pull in relevant &lt;code class=&quot;highlighter-rouge&quot;&gt;posts&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;themes&lt;/code&gt;, resulting in two &lt;code class=&quot;highlighter-rouge&quot;&gt;JOIN&lt;/code&gt; clauses in the query.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: This is just one solution for this particular problem with its own downsides. Any memory concerns dealing with a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; that has far too many &lt;code class=&quot;highlighter-rouge&quot;&gt;posts&lt;/code&gt; or similar problems are not addressed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Opening up New Relic shows the the improvement:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/graph_after_fix.png&quot; alt=&quot;New Relic Transaction Trace Graph After Fix&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A request previously rendering in 200ms is now as low as 40ms.&lt;/p&gt;

&lt;p&gt;The breakdown of the transaction call count shows improvement as well:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/call_count_table_after_fix.png&quot; alt=&quot;New Relic Transaction Call Count Table After Fix&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;measure-twice-measure-again-just-keep-measuring&quot;&gt;Measure Twice, Measure Again, Just Keep Measuring&lt;/h2&gt;

&lt;p&gt;Understanding slow parts of a production Ruby on Rails application can mean the difference between an “OK” user experience and a great one. When developing these applications, it can be hard to keep track of every inefficiency that could result in sub-optimal &lt;code class=&quot;highlighter-rouge&quot;&gt;N + 1&lt;/code&gt; behaviour. Both new and seasoned Ruby on Rails applications can be vulnerable to these types of problems, knowing how to diagnose them is the first step towards their resolution.&lt;/p&gt;

&lt;p&gt;New Relic was a crucial element in this example but it is not the only tool available. Many other analysis tools for Ruby on Rails applications exist and Rails itself gives developers insight into an application’s behaviour via its logs.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Things to Consider when Metaprogramming in Ruby</title>
   <link href="https://jakeyesbeck.com/2016/04/10/things-to-consider-when-metaprogramming-in-ruby/"/>
   <updated>2016-04-10T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/04/10/things-to-consider-when-metaprogramming-in-ruby</id>
   <content type="html">&lt;p&gt;Metaprogramming in Ruby is a polarizing topic. The most common purpose of Ruby metaprogramming is for code to alter itself at runtime. Metaprogramming can be used to achieve terse and more flexible code. However, it is not without its cost. As with most things, nothing of value is free, even metaprogramming.&lt;/p&gt;

&lt;p&gt;Undoubtedly, there is a time and place for metaprogramming; but, awareness of concessions that need to be made to support a metaprogrammed solution is important.&lt;/p&gt;

&lt;h2 id=&quot;code-discovery-and-readability&quot;&gt;Code Discovery and Readability&lt;/h2&gt;

&lt;p&gt;One problem with metaprogramming solutions are their obstruction of code discovery. When entering a new project or simply trying to re-familiarize oneself with an existing one, tracing code execution in a text editor can be quite difficult if method definitions do not exist.&lt;/p&gt;

&lt;p&gt;For example, we can assume that a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class exists with a set of metaprogrammed methods:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:last_name&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;has_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Although a little contrived, this code is a list of simple convenience methods on a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class. This solution is easily extended to include additional attributes without a full method definition per attribute.&lt;/p&gt;

&lt;p&gt;However, these methods can not be found using &lt;code class=&quot;highlighter-rouge&quot;&gt;grep&lt;/code&gt;, silver searcher, or other “find all” tools. Since the method &lt;code class=&quot;highlighter-rouge&quot;&gt;has_password?&lt;/code&gt; is never explicitly defined in the code, it is not discoverable.&lt;/p&gt;

&lt;h3 id=&quot;a-work-around&quot;&gt;A Work Around:&lt;/h3&gt;

&lt;p&gt;To combat this issue, some developers choose to write a comment listing the defined method names above the metaprogramming block. This simple solution can greatly help the readability of the code:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# has_password?, has_email?, has_first_name?,&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#  has_last_name? method definitions&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:last_name&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;has_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;Depending on the amount of times a piece of code is executed, performance considerations can be extremely important. “Hot code” is a term used to describe code that is called frequently during an application’s request cycle. Since not all code is created equally, understanding the performance implications of different metaprogramming approaches is imperative when writing or modifying hot code.&lt;/p&gt;

&lt;h3 id=&quot;the-setup&quot;&gt;The Setup&lt;/h3&gt;

&lt;p&gt;An example application needs to handle incoming data at scale. Upon receiving the data, it must make it accessible to the rest of the application. Myriad options exist to solve this problem, but we can assume that only a few are feasible for this Ruby codebase.&lt;/p&gt;

&lt;p&gt;The incoming data looks like the following:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Some User&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;phones&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;818-555-5555&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;415-555-5555&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;email@whatever.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;birthday&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;12-12-1900&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: This data will be referred to in the following examples as &lt;code class=&quot;highlighter-rouge&quot;&gt;incoming_data&lt;/code&gt; and we can assume it was been decoded from &lt;code class=&quot;highlighter-rouge&quot;&gt;JSON&lt;/code&gt; into a Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;all-methods&quot;&gt;1. All Methods&lt;/h3&gt;

&lt;p&gt;One way to accept and integrate this incoming data would be create a class which maps all attributes under the &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;user&#39;&lt;/code&gt; key to methods:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserMetaMethods&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each_pair&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:attr_accessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserMetaMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; email@whatever.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This solution makes accessing the incoming data very consumer friendly. All attributes appear as methods that return positively to &lt;code class=&quot;highlighter-rouge&quot;&gt;respond_to?&lt;/code&gt; and have corresponding instance variables per attribute.&lt;/p&gt;

&lt;h3 id=&quot;methodmissing&quot;&gt;2. &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;A group of metaprogramming solutions would not be complete without one utilizing &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt;. With &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt;, a non-existent method call can be intercepted on an object and evaluated with additional data unbeknownst to the original caller.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserMethodMissing&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method_missing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;key?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;respond_to_missing?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;include_private&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;key?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserMethodMissing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; email@whatever.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;respond_to_missing?&lt;/code&gt; method is also defined to enable &lt;code class=&quot;highlighter-rouge&quot;&gt;respond_to?&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;method&lt;/code&gt; calls to execute successfully. &lt;a href=&quot;https://robots.thoughtbot.com/always-define-respond-to-missing-when-overriding&quot;&gt;Read more information about &lt;code class=&quot;highlighter-rouge&quot;&gt;respond_to_missing?&lt;/code&gt; here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Patterns equivalent to this are used in some popular libraries like &lt;code class=&quot;highlighter-rouge&quot;&gt;OpenStruct&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Hashie&lt;/code&gt; to achieve similar results.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;regular-object&quot;&gt;3. “Regular” Object&lt;/h3&gt;

&lt;p&gt;As a control, a regular Ruby object can be created with specific attributes defined:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserRegular&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;ss&quot;&gt;:phones&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;ss&quot;&gt;:birthday&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;name&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@phones&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;phones&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;email&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@birthday&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;birthday&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserRegular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; email@whatever.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;An immediate downside to this approach is: if the contract of the external service changes this object may not be initialized with all pertinent data.&lt;/p&gt;

&lt;h3 id=&quot;a-hash&quot;&gt;4. A &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;No additional code is required for this approach, a consumer would simply use the resulting Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt; after the received &lt;code class=&quot;highlighter-rouge&quot;&gt;JSON&lt;/code&gt; is parsed:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;email&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; email@whatever.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Not a metaprogramming solution, but still a valid way of handling the passed in data. Using a simple &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt; does not grant the flexibility of the other solutions but can be a great base-case for performance testing.&lt;/p&gt;

&lt;h3 id=&quot;how-they-compare&quot;&gt;How They Compare&lt;/h3&gt;

&lt;p&gt;Finally, the exciting part: potentially relevant performance benchmarks.&lt;/p&gt;

&lt;p&gt;The library we will use to test how each of these solutions does is &lt;a href=&quot;https://github.com/evanphx/benchmark-ips&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;benchmark/ips&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This library makes it simple to define different implementation sections and then compare them:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;benchmark/ips&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ips&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;UserMetaMethods&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserMetaMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;UserMethodMissing&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserMethodMissing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;UserRegular&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserRegular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Hash&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;email&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compare!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Each &lt;code class=&quot;highlighter-rouge&quot;&gt;report&lt;/code&gt; corresponds to a solution described above. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt; report did not &lt;em&gt;need&lt;/em&gt; to initialize a new object, but for consistency’s sake, a new &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt; is initialized from everything under the &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;user&#39;&lt;/code&gt; key of the original &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Running this code results in:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Calculating -------------------------------------
   UserMetaMethods     79.294  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 2.5%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -    399.000
 UserMethodMissing      1.531k &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 1.2%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -      7.791k
       UserRegular    913.295  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 1.4%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -      4.628k
              Hash      3.141k &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 1.0%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -     15.860k

Comparison:
              Hash:     3141.2 i/s
 UserMethodMissing:     1530.5 i/s - 2.05x slower
       UserRegular:      913.3 i/s - 3.44x slower
   UserMetaMethods:       79.3 i/s - 39.61x slower
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Wow! Aside from simply using a &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt; implementation is the fastest. Quick, everyone go change all the code to use &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt;! No. Stop. Do not do that.&lt;/p&gt;

&lt;p&gt;While it might be faster than the &lt;code class=&quot;highlighter-rouge&quot;&gt;UserRegular&lt;/code&gt; implementation, it is not without its drawbacks. A &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt; solution certainly has value in a variety of situations but a simple benchmark should not persuade anyone to simply switch their code around to gain the “speed up”.&lt;/p&gt;

&lt;p&gt;What about existing libraries that have similar behaviour to &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt; (i.e. &lt;code class=&quot;highlighter-rouge&quot;&gt;Hashie&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;OpenStruct&lt;/code&gt;)?&lt;/p&gt;

&lt;p&gt;To add them to the existing benchmark, the corresponding classes must be made:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;ostruct&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserOpenStruct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;OpenStruct&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;hashie&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserMash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hashie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Mash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then two new &lt;code class=&quot;highlighter-rouge&quot;&gt;report&lt;/code&gt; calls can add them to the existing benchmark:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ips&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;OpenStruct&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserOpenStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;UserMash&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserMash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incoming_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The results of these two additions is a bit of a surprise:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Calculating -------------------------------------
   UserMetaMethods     79.050  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 2.5%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -    399.000
 UserMethodMissing      1.537k &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 1.3%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -      7.752k
       UserRegular    914.824  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 1.4%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -      4.576k
        OpenStruct     49.954  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 6.0%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -    250.000
          UserMash    194.411  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 1.5%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -    988.000
              Hash      3.140k &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;± 0.9%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; i/s -     15.759k

Comparison:
              Hash:     3140.1 i/s
 UserMethodMissing:     1536.9 i/s - 2.04x slower
       UserRegular:      914.8 i/s - 3.43x slower
          UserMash:      194.4 i/s - 16.15x slower
   UserMetaMethods:       79.0 i/s - 39.72x slower
        OpenStruct:       50.0 i/s - 62.86x slower
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Despite &lt;code class=&quot;highlighter-rouge&quot;&gt;OpenStruct&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Hashie&lt;/code&gt; seeming very similar to our homegrown &lt;code class=&quot;highlighter-rouge&quot;&gt;method_missing&lt;/code&gt; solution, both yielded worse results. However, like other metaprogramming solutions, both &lt;code class=&quot;highlighter-rouge&quot;&gt;OpenStruct&lt;/code&gt; and  &lt;code class=&quot;highlighter-rouge&quot;&gt;Hashie&lt;/code&gt; make up for this speed deficiency with flexibility.&lt;/p&gt;

&lt;p&gt;If this were a real problem in a production application, &lt;code class=&quot;highlighter-rouge&quot;&gt;OpenStruct&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Hashie&lt;/code&gt; could certainly both be viable solutions. Unless the code path to utilize these libraries was scorching hot, their performance issues might not be a factor.&lt;/p&gt;

&lt;h2 id=&quot;why-the-slowdown&quot;&gt;Why the Slowdown?&lt;/h2&gt;

&lt;p&gt;The reason that some metaprogramming solutions are slow has partially to do with the Ruby inline method cache. In Ruby, the inline method cache is responsible for storing methods that it knows about so as to avoid a costly look up operation every time. Metaprogramming interferes with this built in cache by invalidating its cache key.&lt;/p&gt;

&lt;p&gt;Every time a class is reopened or a method is defined on a class, pieces of the inline method cache key change, resulting in a cache miss and method lookup. Metaprogrammed code (especially code that executes at every &lt;code class=&quot;highlighter-rouge&quot;&gt;Object.new&lt;/code&gt; like &lt;code class=&quot;highlighter-rouge&quot;&gt;UserMetaMethods&lt;/code&gt;) does not benefit from the inline method caching in the same ways as “normal” code does. For much more information, &lt;a href=&quot;https://tenderlovemaking.com/2015/12/23/inline-caching-in-mri.html&quot;&gt;a man much smarter than I wrote a great article explaining Ruby inline method caching in detail&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;use-the-right-tool-for-the-job&quot;&gt;Use the Right Tool for the Job&lt;/h2&gt;

&lt;p&gt;When iterating through a list of options, no single data point is sufficient enough to rule one option superior to all others. Benchmarks should be treated as a single data point and bring depth to a comparison, not rule it. After all, who cares how slow a piece of code is if it is never run?&lt;/p&gt;

&lt;p&gt;Metaprogramming is a very powerful tool in the Ruby language that should be wielded with care. Like anything, using metaprogramming too much can cause unmaintainable code. This sort of code might be great for job security, but could be less performant, unreadable, and unmaintainable by coworkers.&lt;/p&gt;

&lt;p&gt;When used correctly and in appropriate circumstances, metaprogramming can be a great asset. The trick is knowing when to use it and when to refrain. Sometimes just using a &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt; might be the best solution.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Deal with Timezones the Active Support Way</title>
   <link href="https://jakeyesbeck.com/2016/04/03/how-to-deal-with-timezones-the-active-support-way/"/>
   <updated>2016-04-03T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/04/03/how-to-deal-with-timezones-the-active-support-way</id>
   <content type="html">&lt;p&gt;&lt;em&gt;“Well the code is bad because we had to…”&lt;/em&gt; is a phrase one might hear when discussing timezone offsets or daylight savings time considerations.&lt;/p&gt;

&lt;p&gt;Unless a developer is fortunate enough to work at a company whose userbase is entirely located in the UTC timezone, writing software aware of different timezones can be a daunting task. Luckily, Ruby on Rails’ &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveSupport&lt;/code&gt; library has some very nice built in features that can prove invaluable when facing time related issues.&lt;/p&gt;

&lt;h2 id=&quot;built-in-timezones&quot;&gt;Built-in Timezones&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveSupport&lt;/code&gt; in Ruby on Rails 4.0+ has a built in list of all supported timezones on the &lt;code class=&quot;highlighter-rouge&quot;&gt;TimeZone&lt;/code&gt; class:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TimeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&quot;American Samoa&quot;, &quot;International Date Line West&quot;, &quot;Midway Island&quot;, &quot;Hawaii&quot;, &quot;Alaska&quot;, &quot;Pacific Time (US &amp;amp; Canada)&quot;, &quot;Tijuana&quot;, &quot;Arizona&quot;, &quot;Chihuahua&quot;, &quot;Mazatlan&quot;, &quot;Mountain Time (US &amp;amp; Canada)&quot;, &quot;Central America&quot;, &quot;Central Time (US &amp;amp; Canada)&quot;, &quot;Guadalajara&quot;, ...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This list of timezones can be used when parsing strings into &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; objects and converting an existing &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; object from one timezone to another. For working with timezones in the United States, a handy &lt;code class=&quot;highlighter-rouge&quot;&gt;us_zones&lt;/code&gt; method is also available on the same class.&lt;/p&gt;

&lt;p&gt;One interesting detail about this list of timezones is the lack of daylight savings time qualifiers. Keeping the timezones agnostic of daylight savings helps simplify their use. A developer does not need to worry about using one timezone object over another due to the time of the year.&lt;/p&gt;

&lt;h2 id=&quot;timeusezone&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Time.use_zone&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveSupport&lt;/code&gt; library adds some functionality to built in Ruby classes. One of those additions is the ability to set and retrieve the &lt;code class=&quot;highlighter-rouge&quot;&gt;zone&lt;/code&gt; attribute on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; class. After a &lt;code class=&quot;highlighter-rouge&quot;&gt;zone&lt;/code&gt; is set, it can be used when parsing strings into &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; objects:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Pacific Time (US &amp;amp; Canada)&#39;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2016-04-01 10:00:00&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Fri, 01 Apr 2016 10:00:00 PDT -07:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code takes a timestamp string without a timezone specified and uses the value of &lt;code class=&quot;highlighter-rouge&quot;&gt;Time.zone&lt;/code&gt; to correctly represent the time in the Pacific timezone.&lt;/p&gt;

&lt;p&gt;However, an immediate red flag is present in this code. The &lt;code class=&quot;highlighter-rouge&quot;&gt;zone&lt;/code&gt; attribute persists for the rest of the Ruby runtime, potentially causing unexpected behaviour at a later time.&lt;/p&gt;

&lt;p&gt;Luckily, &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveSupport&lt;/code&gt; solves this problem with the &lt;code class=&quot;highlighter-rouge&quot;&gt;use_zone&lt;/code&gt; method. This method accepts the same set of strings as its single argument and expects a block.&lt;/p&gt;

&lt;p&gt;Within the passed in block is the only place &lt;code class=&quot;highlighter-rouge&quot;&gt;Time.zone&lt;/code&gt; is affected, eliminating the possibility of a &lt;code class=&quot;highlighter-rouge&quot;&gt;zone&lt;/code&gt; sticking around longer than intended:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &quot;UTC&quot;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;use_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Pacific Time (US &amp;amp; Canada)&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;Pacific Time (US &amp;amp; Canada)&quot;&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2016-04-01 10:00:00&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Fri, 01 Apr 2016 10:00:00 PDT -07:00&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &quot;UTC&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This temporary &lt;code class=&quot;highlighter-rouge&quot;&gt;zone&lt;/code&gt; setting can be very helpful if a set of users are processed, each with their own respective timezone.&lt;/p&gt;

&lt;h2 id=&quot;timewithzoneintimezone&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;TimeWithZone.in_time_zone&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;When dealing with &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Date&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; objects, converting each from one timezone to another can be tedious. The &lt;code class=&quot;highlighter-rouge&quot;&gt;in_time_zone&lt;/code&gt; method removes some complexity from those operations.&lt;/p&gt;

&lt;p&gt;Used alone, the &lt;code class=&quot;highlighter-rouge&quot;&gt;in_time_zone&lt;/code&gt; can transform an existing object into an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;TimeWithZone&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2016-04-04 03:55:24 +0000&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;in_time_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Hawaii&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Sun, 03 Apr 2016 17:55:24 HST -10:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In any sane system, timestamps in a database are always stored in UTC, aka Zulu, time. When exposing these timestamps to users, the &lt;code class=&quot;highlighter-rouge&quot;&gt;in_time_zone&lt;/code&gt; method can quickly switch the timestamp to a user’s local time.&lt;/p&gt;

&lt;p&gt;To see a more creative use of &lt;code class=&quot;highlighter-rouge&quot;&gt;in_time_zone&lt;/code&gt;, we can assume that an application must solve a scheduling problem. An example application wants to send its users an email at the exact same time relative to a user’s timezone. Regardless of where a user lives, they should receive an email at 10:30 AM local time.&lt;/p&gt;

&lt;p&gt;A naive approach might not yield the intended result:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;time_zone&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Hawaii&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;send_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2016&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;04&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2016-04-01 10:30:00 +0000&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;send_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;in_time_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;time_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Fri, 01 Apr 2016 00:30:00 HST -10:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Whoops, that is not right at all. This code initialized a &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; object for the “correct” send time but then &lt;code class=&quot;highlighter-rouge&quot;&gt;in_time_zone&lt;/code&gt; not only moved the timezone of that object, it also modified the actual time. This would result in all users getting an email at the same exact moment but at an inconvenient time relative to where they live.&lt;/p&gt;

&lt;p&gt;Potential solutions to this problem might include modifying the timezone part of an outputted string (the &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;+0000&quot;&lt;/code&gt; at the end) and re-parsing it, but that solution can be prone to error and hard to understand.&lt;/p&gt;

&lt;p&gt;Since the &lt;code class=&quot;highlighter-rouge&quot;&gt;in_time_zone&lt;/code&gt; method works on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Date&lt;/code&gt; class, the simplest approach would be to initialize a new &lt;code class=&quot;highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; object in a user’s timezone and add 10.5 hours to it:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;time_zone&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Hawaii&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;beginning_of_day&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;in_time_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;time_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Sun, 03 Apr 2016 00:00:00 HST -10:00&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;beginning_of_day&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hours&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Sun, 03 Apr 2016 10:30:00 HST -10:00&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ImportantEmailSender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send_at!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Great! An email will be sent at 10:30 AM Hawaii time and we successfully avoided any time string munging or other strange object casting. A user in London can also receive an email at exactly 10:30 AM their local time and this code need not grow in complexity.&lt;/p&gt;

&lt;h2 id=&quot;saving-time&quot;&gt;Saving Time&lt;/h2&gt;

&lt;p&gt;Whether in code or everyday life, it seems that struggling with time is something we as humans are simply destined to do. Some good news is that &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveSupport&lt;/code&gt; may not grant you any more wall clock time, but could save you some when wrangling different pieces of scheduling code together.&lt;/p&gt;

&lt;p&gt;As usual, the API of the &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveSupport::TimeZone&lt;/code&gt; class is much larger than just the two methods illustrated here. For more information, the &lt;a href=&quot;https://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html&quot;&gt;offical ActiveSupport documentation&lt;/a&gt; is a great place to read further.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Five More Active Record Features You Should Be Using</title>
   <link href="https://jakeyesbeck.com/2016/03/27/five-more-active-record-features-you-should-be-using/"/>
   <updated>2016-03-27T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/03/27/five-more-active-record-features-you-should-be-using</id>
   <content type="html">&lt;p&gt;In a &lt;a href=&quot;https://jakeyesbeck.com/2015/11/15/five-active-record-features-you-should-be-using/&quot;&gt;previous post&lt;/a&gt;, I illustrated a few helpful &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; features. The entire API of &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; cannot possibly be contained within a single or even a handful of digestible posts; but, here are at least five more pieces of that massive API that some might find useful.&lt;/p&gt;

&lt;p&gt;Just like before, the example application used to demonstrate these features will be an imaginary Ruby on Rails application: &lt;em&gt;“booksandreviews.com”&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:reviews&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:book&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;pluck&quot;&gt;1. &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Introduced in Ruby on Rails 4.0, the &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; method helps keep memory allocation to a minimum when returning results from &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; queries. A great use case for the &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; method is when a database table backing an &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; object has a very large number of columns. In this situation, returning an object’s full dataset can be cause unnecessary memory allocation and potentially expensive deserialization (in the case of custom or JSON serialized columns).&lt;/p&gt;

&lt;p&gt;To get a list of &lt;code class=&quot;highlighter-rouge&quot;&gt;book_ids&lt;/code&gt; from the &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;fantasy&#39;&lt;/code&gt; genre, the &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; method is a simple to use:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;genre: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;fantasy&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pluck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# SELECT &quot;books&quot;.&quot;id&quot; FROM &quot;books&quot; WHERE &quot;books&quot;.&quot;genre&quot; = &#39;fantasy&#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;An important thing to recognize about the &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; method is its return value. Unlike its cousin, &lt;code class=&quot;highlighter-rouge&quot;&gt;select&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; method does not return an &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Multiple column names may be passed to &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; and the values of these columns will be returned in a nested &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt;. The returned &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt; will maintain the order of columns to how they were requested:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;genre: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;fantasy&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pluck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# SELECT &quot;books&quot;.&quot;id&quot;, &quot;books&quot;.&quot;title&quot; FROM &quot;books&quot; WHERE &quot;books&quot;.&quot;genre&quot; = &#39;fantasy&#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Title&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Another One&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;While possible, it might not always be the best idea to request multiple columns in a single &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; call. Too many columns can produce an unruly result and nullify the performance gain &lt;code class=&quot;highlighter-rouge&quot;&gt;pluck&lt;/code&gt; provided in the first place.&lt;/p&gt;

&lt;h2 id=&quot;transaction&quot;&gt;2. &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;An important aspect of relational databases is its atomic behaviour. When creating &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; objects, maintaining this aspect is possible through the use of the &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;For instance, if an exception occurs during the update of all of a &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&#39;s&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Reviews&lt;/code&gt;, a &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt; can help mitigate harmful side-effects:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;meaningful_update!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If the &lt;code class=&quot;highlighter-rouge&quot;&gt;meaningful_update!&lt;/code&gt; method throws an exception, all reviews before the erroring review will update appropriately and all after will not. If this method has a compounding side-effect (like incrementing a field), iterating through all reviews again would be harmful.&lt;/p&gt;

&lt;p&gt;With a &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt;, this problem does not exist:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;meaningful_update!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After adding the &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt;, this new code will revert all changes contained within the &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt; if an exception is raised. It is equivalent to updating all records in a single query.&lt;/p&gt;

&lt;h2 id=&quot;aftercommit&quot;&gt;3. &lt;code class=&quot;highlighter-rouge&quot;&gt;after_commit&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Love them or hate them, callbacks in Ruby on Rails are a viable option to solve many problems. &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; callbacks are initiated at different times depending on the operation a model is about to undergo.&lt;/p&gt;

&lt;p&gt;A fairly common use case for callbacks in Ruby on Rails revolves around what to do after a model is persisted. A model can be persisted by either &lt;code class=&quot;highlighter-rouge&quot;&gt;save&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;create&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;update&lt;/code&gt;. Since the concept of “saving” is the common denominator for all these methods, it would be reasonable to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;after_save&lt;/code&gt; to trigger logic that should follow one of these persistence operations.&lt;/p&gt;

&lt;p&gt;To add a new &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; to a queue for a &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; after it is saved:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;after_save&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:enqueue_for_review&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enqueue_for_review&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;book_id: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Added &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to ReviewQueue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We can assume that the &lt;code class=&quot;highlighter-rouge&quot;&gt;ReviewQueue&lt;/code&gt; is a key/value storage (Redis or something similar) backed object whose purpose is to place new &lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt; into a queue for critics to review. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Logger&lt;/code&gt; class simply outputs text to &lt;code class=&quot;highlighter-rouge&quot;&gt;stdout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When everything goes well, the callback works beautifully:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;A New Book&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;author_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;content: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Blah blah...&#39;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Added 4 to ReviewQueue&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &amp;lt;Book id: 4, title: &#39;A New Book&#39; ..&amp;gt;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, if this code was wrapped in a &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt;, and that &lt;code class=&quot;highlighter-rouge&quot;&gt;transaction&lt;/code&gt; fails, the &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; will not persist but the element on in the Redis-backed &lt;code class=&quot;highlighter-rouge&quot;&gt;ReviewQueue&lt;/code&gt; remains.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;A New Book&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;author_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;content: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Blah blah...&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;StandardError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Something Happened&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Added 4 to ReviewQueue&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Error &#39;Something Happened&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code has now generated an element on the &lt;code class=&quot;highlighter-rouge&quot;&gt;ReviewQueue&lt;/code&gt; for a non-existent &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;; however, if the &lt;code class=&quot;highlighter-rouge&quot;&gt;after_commit&lt;/code&gt; callback is used, this problem will fade away.&lt;/p&gt;

&lt;p&gt;Replacing &lt;code class=&quot;highlighter-rouge&quot;&gt;after_save&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;after_commit&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;after_commit&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:enqueue_for_review&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The same code results a much more desirable outcome:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;A New Book&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;author_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;content: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Blah blah...&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;StandardError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Something Happened&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Error &#39;Something Happened&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Awesome, the &lt;code class=&quot;highlighter-rouge&quot;&gt;after_commit&lt;/code&gt; callback is only triggered after the record is persisted to the database, exactly what we wanted. Ruby on Rails provides &lt;a href=&quot;https://guides.rubyonrails.org/active_record_callbacks.html&quot;&gt;many more callback hooks&lt;/a&gt; besides &lt;code class=&quot;highlighter-rouge&quot;&gt;after_commit&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;touch&quot;&gt;4. &lt;code class=&quot;highlighter-rouge&quot;&gt;touch&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;To update a single timestamp column on an &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; object, &lt;code class=&quot;highlighter-rouge&quot;&gt;touch&lt;/code&gt; is a great option. This method can accept the column name which should be updated in addition to an object’s &lt;code class=&quot;highlighter-rouge&quot;&gt;:updated_at&lt;/code&gt; (if present).&lt;/p&gt;

&lt;p&gt;A great time to utilize the &lt;code class=&quot;highlighter-rouge&quot;&gt;touch&lt;/code&gt; method is when tracking when a record was last viewed. The good people at &lt;em&gt;“booksandreviews.com”&lt;/em&gt; need to be sure their &lt;code class=&quot;highlighter-rouge&quot;&gt;Reviews&lt;/code&gt; are being seen and want to know which &lt;code class=&quot;highlighter-rouge&quot;&gt;Reviews&lt;/code&gt; have not been viewed in a while.&lt;/p&gt;

&lt;p&gt;If the &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; table has a &lt;code class=&quot;highlighter-rouge&quot;&gt;last_viewed_at&lt;/code&gt; column which is of type &lt;code class=&quot;highlighter-rouge&quot;&gt;timestamp&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;touch&lt;/code&gt; can easily update this column in a controller action:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReviewsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:last_viewed_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A request which calls this controller action will result in the query:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;reviews&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;updated_at&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2016-03-28 00:43:43.616367&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;&quot;last_viewed_at&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2016-03-28 00:43:43.616367&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;reviews&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;id&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Unlike setting other attributes, the &lt;code class=&quot;highlighter-rouge&quot;&gt;touch&lt;/code&gt; method invokes an update query right away.&lt;/p&gt;

&lt;h2 id=&quot;changes&quot;&gt;5. &lt;code class=&quot;highlighter-rouge&quot;&gt;changes&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; keeps a sizable amount of information about an object while it undergoes updates. A hash, accessible via the &lt;code class=&quot;highlighter-rouge&quot;&gt;changes&lt;/code&gt; method, acts a central location for these updates. Additionally, &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; exposes a number of per-attribute helper methods to give even more visibility.&lt;/p&gt;

&lt;p&gt;Each key in the &lt;code class=&quot;highlighter-rouge&quot;&gt;changes&lt;/code&gt; hash maps to a record’s attribute. The value of each key is an Array with two elements: what the attribute value used to be, and what it is now:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;book_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;changes&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {&quot;book_id&quot;=&amp;gt;[4, 5]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;a-changed&quot;&gt;a. &lt;code class=&quot;highlighter-rouge&quot;&gt;changed?&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;A simple boolean method &lt;code class=&quot;highlighter-rouge&quot;&gt;changed?&lt;/code&gt; is available to determine if anything on the object is different since its retrieval.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;book_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;changed?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, if the same value is set on a model, regardless of the value’s &lt;code class=&quot;highlighter-rouge&quot;&gt;object_id&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;changed?&lt;/code&gt; returns &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;A Book&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;object_id&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2158279020&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;A Book&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;changed?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;object_id&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2158274600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Two “different” strings were set to &lt;code class=&quot;highlighter-rouge&quot;&gt;book.title&lt;/code&gt; but since they resolve to the same characters, the object is not &lt;code class=&quot;highlighter-rouge&quot;&gt;changed?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When using PostgreSQL, the &lt;code class=&quot;highlighter-rouge&quot;&gt;changed?&lt;/code&gt; method can save unnecessary &lt;code class=&quot;highlighter-rouge&quot;&gt;begin&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;commit&lt;/code&gt; transaction calls for objects that have no changes:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BooksController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sanitized_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assign_attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sanitized_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;changed?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;b-attributewas&quot;&gt;b. &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;attribute&amp;gt;_was&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Accessing the same &lt;code class=&quot;highlighter-rouge&quot;&gt;changes&lt;/code&gt; hash as the &lt;code class=&quot;highlighter-rouge&quot;&gt;changed?&lt;/code&gt; method, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;attribute&amp;gt;_was&lt;/code&gt; returns the value of an attribute before it was reassigned:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Approved&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;status_was&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;Pending&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If a &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&#39;s&lt;/code&gt; status moving from &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;Pending&quot;&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;Approved&quot;&lt;/code&gt; should remove it from an approval queue, the &lt;code class=&quot;highlighter-rouge&quot;&gt;status_was&lt;/code&gt; method can be utilized in a callback:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Review&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_save&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:maybe_remove_from_review_queue&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maybe_remove_from_review_queue&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Approved&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;status_was&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Pending&#39;&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To verify the result, we can check that the &lt;code class=&quot;highlighter-rouge&quot;&gt;ReviewQueue&lt;/code&gt; decrements its internal count of reviews pending review:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;status&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;Pending&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Approved&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;ReviewQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: Additional considerations might need to be made since the &lt;code class=&quot;highlighter-rouge&quot;&gt;save&lt;/code&gt; is not guaranteed to persist like described above in the &lt;code class=&quot;highlighter-rouge&quot;&gt;after_commit&lt;/code&gt; example.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Build a Ruby on Rails Engine</title>
   <link href="https://jakeyesbeck.com/2016/03/20/how-to-build-a-ruby-on-rails-engine/"/>
   <updated>2016-03-20T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/03/20/how-to-build-a-ruby-on-rails-engine</id>
   <content type="html">&lt;p&gt;Ruby on Rails Engines are miniature applications whose purpose is to supplement a larger Ruby on Rails application. If functionality can exist independent from a main application, an Engine can provide a wonderful degree of encapsulation.&lt;/p&gt;

&lt;p&gt;Recently, I created the and “gemified” the &lt;a href=&quot;https://jakeyesbeck.com/2016/01/03/passages/&quot;&gt;Passages Ruby on Rails Engine&lt;/a&gt; to help alleviate some routing frustration. This gem will be the be used as the example for demonstrating what goes into creating a Ruby on Rails Engine.&lt;/p&gt;

&lt;h2 id=&quot;revving-up&quot;&gt;Revving Up&lt;/h2&gt;

&lt;p&gt;There are two ways to start building an Engine. One option is to use the built in generators to create directories and dummy classes. These generators behave in the same way as standard Rails generators.&lt;/p&gt;

&lt;p&gt;To generate an Engine in this way, use the &lt;code class=&quot;highlighter-rouge&quot;&gt;plugins&lt;/code&gt; built in generator:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rails plugin new passages --mountable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: Engines and Plugins are not exactly the same in the Ruby on Rails world but the &lt;code class=&quot;highlighter-rouge&quot;&gt;--mountable&lt;/code&gt; flag tells the plugin generator to generate a full Engine.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The other approach is to simply create the needed directories and files by hand. This is was the way the Passages Engine was built, resulting in the following directory structure:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; |-app
 |--controllers
 |---passages
 |----&amp;lt;controller directories&amp;gt;
 |--views
 |---passages
 |----&amp;lt;views directories&amp;gt;
 |-config
 |--routes.rb
 |--initializers
 |---assets.rb
 |-lib
 |--passages
 |---engine.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Some directories that the &lt;code class=&quot;highlighter-rouge&quot;&gt;rails&lt;/code&gt; generator would have added are missing (i.e. &lt;code class=&quot;highlighter-rouge&quot;&gt;models&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;helpers&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;mailers&lt;/code&gt;). These directories might be necessary for some projects, but the Passages Engine did not have use for them.&lt;/p&gt;

&lt;p&gt;The file at the heart of it all is &lt;code class=&quot;highlighter-rouge&quot;&gt;engine.rb&lt;/code&gt;. This file is responsible for defining the engine and will also be utilized later to add optional enhancements an Engine can take advantage of:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Passages&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Engine&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;isolate_namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Passages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;An interesting line in this file is the &lt;code class=&quot;highlighter-rouge&quot;&gt;isolate_namespace&lt;/code&gt; method call. This method helps ensure encapsulation for the Engine by isolating its controllers, helpers, views, routes, and any other shared resources between the main application and the Engine.&lt;/p&gt;

&lt;p&gt;With isolation, an Engine does not need to worry about conflicting class or module names in the main application. Additionally, an isolated Engine will set its own name according to its namespace, accessible later via &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages::Engine.engine_name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since the Passages Engine is also a gem, it has a file named &lt;code class=&quot;highlighter-rouge&quot;&gt;passages.rb&lt;/code&gt; in its &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; directory:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Passages&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;passages/engine&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;controllers/passages/routes_controller&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This file is responsible for defining the &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; module and requiring the engine. It is the entry point for this gem’s logic.&lt;/p&gt;

&lt;h2 id=&quot;encapsulate-everywhere&quot;&gt;Encapsulate Everywhere&lt;/h2&gt;

&lt;p&gt;The overarching theme of designing a good Ruby on Rails Engine is encapsulation. An application should not be negatively affected by its underlying Engines, they should simply support and bring new functionality the application.&lt;/p&gt;

&lt;p&gt;To help reinforce this theme, Ruby on Rails requires that an Engine’s controllers, views, and assets all be nested in namespace modules and corresponding directory folders.&lt;/p&gt;

&lt;h3 id=&quot;controllers&quot;&gt;Controllers&lt;/h3&gt;

&lt;p&gt;In the Passages Engine, the &lt;code class=&quot;highlighter-rouge&quot;&gt;RoutesController&lt;/code&gt; demonstrates this nesting.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; |-app
 |--controllers
 |---passages
 |----routes_controller.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Passages&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RoutesController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The same folder structure is used for views and assets.&lt;/p&gt;

&lt;h3 id=&quot;routes&quot;&gt;Routes&lt;/h3&gt;

&lt;p&gt;Of course what good is a controller without a route to use it? A Ruby on Rails Engine also can define its own routes similarly to a stand-alone application.&lt;/p&gt;

&lt;p&gt;Unlike the controllers, the &lt;code class=&quot;highlighter-rouge&quot;&gt;routes.rb&lt;/code&gt; file is not contained in a &lt;code class=&quot;highlighter-rouge&quot;&gt;passages&lt;/code&gt; folder, nor is it within the &lt;code class=&quot;highlighter-rouge&quot;&gt;module Passages&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; |-config
 |--routes.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Passages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;to: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;routes#index&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In a standard Ruby on Rails application, the first line in a routes file is: &lt;code class=&quot;highlighter-rouge&quot;&gt;Rails.application.routes.draw&lt;/code&gt;; however, within an Engine, the name of the Engine replaces &lt;code class=&quot;highlighter-rouge&quot;&gt;Rails.application&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With a simple routes file in place, an application using the Passages Engine can run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake routes&lt;/code&gt; to see the new routes in action:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rake routes
     Prefix Verb   URI Pattern
   passages        /passages
      users GET    /users
            POST   /users
   new_user GET    /users/new
  edit_user GET    /users/:id/edit
       user GET    /users/:id
            PATCH  /users/:id
            PUT    /users/:id
            DELETE /users/:id
Routes &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;Passages::Engine:
  root GET  /      passages/routes#index
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Note: This assumes the engine is mounted at &lt;code class=&quot;highlighter-rouge&quot;&gt;/passages&lt;/code&gt;, &lt;a href=&quot;#mount-up&quot;&gt;more about mounting routes below&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Neat, the Passages routes are in a separate section to help differentiate them from normal application routes.&lt;/p&gt;

&lt;p&gt;Remember the &lt;code class=&quot;highlighter-rouge&quot;&gt;isolate_namespace&lt;/code&gt; method? One of the side-effects of &lt;strong&gt;not&lt;/strong&gt; using an isolated namespace can be seen when asking for an applications routes.&lt;/p&gt;

&lt;p&gt;If the namespace isolation is commented out:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Passages&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Engine&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# isolate_namespace(Passages)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then &lt;code class=&quot;highlighter-rouge&quot;&gt;rake routes&lt;/code&gt; gives a different output:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rake routes
         Prefix Verb   URI Pattern
passages_engine        /passages
          users GET    /users
                POST   /users
       new_user GET    /users/new
      edit_user GET    /users/:id/edit
           user GET    /users/:id
                PATCH  /users/:id
                PUT    /users/:id
                DELETE /users/:id

Routes &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;Passages::Engine:
  root GET  /          routes#routes
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Notice that now the &lt;code class=&quot;highlighter-rouge&quot;&gt;root&lt;/code&gt; for the Passages Engine has had its prefix removed. This will cause Rails to look in the wrong place for the &lt;code class=&quot;highlighter-rouge&quot;&gt;routes_controller&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RoutingError&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uninitialized&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RoutesController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;While this might not be a huge deal for some applications, the fact that an Engine triggers a top level controller to be fetched is worrysome. What if the main application had its own &lt;code class=&quot;highlighter-rouge&quot;&gt;RoutesController&lt;/code&gt;, the Passages Engine could incorrectly fetch that instead. Or if things are reversed, an Engine without an isolated namespace might incorrectly override an important controller in the main application.&lt;/p&gt;

&lt;h3 id=&quot;assets&quot;&gt;Assets&lt;/h3&gt;

&lt;p&gt;Like controllers and views, an Engine’s assets are also nested under a folder bearing the Engine’s name.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; |-app
 |--assets
 |---javascripts
 |----passages
 |-----application.js
 |---stylesheets
 |----passages
 |-----application.css
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This organization enables the layouts and other views in the Engine to only load the files it needs and not accidentally reference the main application’s &lt;code class=&quot;highlighter-rouge&quot;&gt;application.js&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;application.css&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;passages/application&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;media: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;all&#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_include_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;passages/application&#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To enable precompiled assets, a few more lines need to be added in the same &lt;code class=&quot;highlighter-rouge&quot;&gt;engine.rb&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Passages&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Engine&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;isolate_namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Passages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;passages.assets.precompile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;precompile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;&#39;application.css&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;&#39;application.js&#39;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This &lt;code class=&quot;highlighter-rouge&quot;&gt;initializer&lt;/code&gt; line creates an initializer in the underlying railties to be evaluated when assets are precompiled via &lt;code class=&quot;highlighter-rouge&quot;&gt;rake assets:precompile&lt;/code&gt;. With this, an application can successfully compile its own assets and those of the Passages Engine.&lt;/p&gt;

&lt;h2 id=&quot;mount-up&quot;&gt;Mount Up&lt;/h2&gt;

&lt;p&gt;A Ruby on Rails Engine must be mounted by an application for it to be accessible.&lt;/p&gt;

&lt;p&gt;The normal place for this to occur is in a main application’s &lt;code class=&quot;highlighter-rouge&quot;&gt;routes.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mount&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Passages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;at: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/passages&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;/passages&#39;&lt;/code&gt; string can be replaced with any desired endpoint, the Engine does not care about the name.&lt;/p&gt;

&lt;p&gt;Alternatively, an Engine can &lt;strong&gt;mount itself&lt;/strong&gt; using the same &lt;code class=&quot;highlighter-rouge&quot;&gt;initializer&lt;/code&gt; method in &lt;code class=&quot;highlighter-rouge&quot;&gt;engine.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Passages&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Engine&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;isolate_namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Passages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;passages&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;after: :load_config_initializers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;prepend&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mount&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Passages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;at: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/passages&#39;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In this case, the initializer has a specific placement: after the configuration initializers are loaded. This initializer then writes to the main application with &lt;code class=&quot;highlighter-rouge&quot;&gt;Rails.application.routes.prepend&lt;/code&gt; and, as the name suggests, prepends the mount to the application’s routes.&lt;/p&gt;

&lt;p&gt;Since the mount is added to the beginning of an application’s routes, it is possible that this mounted path (in this case &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;/passages&#39;&lt;/code&gt;) will be overridden by a route with the same name later on in the main application’s &lt;code class=&quot;highlighter-rouge&quot;&gt;routes.rb&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;After an application mounts the Passages Engine, it can navigate to &lt;code class=&quot;highlighter-rouge&quot;&gt;/passages&lt;/code&gt;. This request would be served by the Passages Engine like a normal Ruby on Rails application request.&lt;/p&gt;

&lt;h4 id=&quot;use-with-caution&quot;&gt;Use With Caution&lt;/h4&gt;

&lt;p&gt;Auto-mounted Engines may sound like a great idea but it might be best to leave that decision to the consumer. A suggested approach to this is have an opt-in functionality with auto-mounting. Placing this logic behind a conditional (based on some kind of configuration variable) gives consumers of this Engine the power of auto-mounting without the worry of “magic” they did not ask for.&lt;/p&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;With the basic structure in place, a new Engine can be built like any other Ruby on Rails application. Controllers and their respective views can be created and placed under the appropriate namespaces and folders. Routes that utilize these controllers can be added as well. Assuming that both the main application and the Engine use the same ORM (or are at least compatible), even models can be created.&lt;/p&gt;

&lt;p&gt;The Passages Engine was built as a standalone gem. Making it available was the same process as creating any other gem. A &lt;code class=&quot;highlighter-rouge&quot;&gt;.gemspec&lt;/code&gt; file was created, the gem was cut to a version, and then finally hosted on Rubygems.org. An application that wishes to use the Passages Engine can install it by adding a new line to the Gemfile: &lt;code class=&quot;highlighter-rouge&quot;&gt;gem &#39;passages&#39;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This same pattern can be used to make any stand alone Ruby on Rails Engine. However, it would be a wise decision to choose specific versions of Ruby on Rails to support. For example, the Passages Engine was built to support Ruby on Rails 4.X, it is not compatible with Ruby on Rails 3.X at all.&lt;/p&gt;

&lt;h2 id=&quot;built-to-last&quot;&gt;Built to Last&lt;/h2&gt;

&lt;p&gt;Going further, the creation of views, initializer files, migrations, and models can all be accomplished the same way one would in a regular Ruby on Rails application.&lt;/p&gt;

&lt;p&gt;Not all of the Passages Engine was discussed in this guide, but feel free to &lt;a href=&quot;https://github.com/yez/passages&quot;&gt;read the source&lt;/a&gt; to find out more information. Also, I am always looking for eager contributors to either submit issues or pull requests with features they need.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Power of Arel</title>
   <link href="https://jakeyesbeck.com/2016/03/13/the-power-of-arel/"/>
   <updated>2016-03-13T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2016/03/13/the-power-of-arel</id>
   <content type="html">&lt;p&gt;Many modern web applications have at least a few overlapping responsibilities. One of these responsibilities deals with maintaining state. A common choice for storing this state is by way of a relational database. Ruby on Rails applications assume the presence of a database by default and communicate with it via &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; is an &lt;strong&gt;O&lt;/strong&gt;bject &lt;strong&gt;R&lt;/strong&gt;elational &lt;strong&gt;M&lt;/strong&gt;apping (ORM). Under the hood, &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; uses a relational algebra library called &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; to compose queries for execution. &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; is a very powerful library readily available for when &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; falls short.&lt;/p&gt;

&lt;h2 id=&quot;the-basics&quot;&gt;The Basics&lt;/h2&gt;

&lt;p&gt;Keeping up with tradition, assume a standard Ruby on Rails application exists with at least two models, &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Post&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;posts&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;integer&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&quot;user_id&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt;   &lt;span class=&quot;s2&quot;&gt;&quot;category&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;updated_at&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;users&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt;   &lt;span class=&quot;s2&quot;&gt;&quot;first_name&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt;   &lt;span class=&quot;s2&quot;&gt;&quot;last_name&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt;   &lt;span class=&quot;s2&quot;&gt;&quot;email&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;updated_at&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:posts&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h4 id=&quot;ask-find-all-posts-within-a-category-belonging-to-a-user&quot;&gt;Ask: Find all posts within a category belonging to a user.&lt;/h4&gt;

&lt;p&gt;For such a simple query, &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; is capable of generating the appropriate SQL statement:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;ss&quot;&gt;category: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;news&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sql&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;posts&quot;.* FROM &quot;posts&quot;  WHERE &quot;posts&quot;.&quot;user_id&quot; = 123 AND &quot;posts&quot;.&quot;category&quot; = &#39;news&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, if the query needed to be more complex, this simple &lt;code class=&quot;highlighter-rouge&quot;&gt;where&lt;/code&gt; clause is not sufficient. For example, instead of all &lt;code class=&quot;highlighter-rouge&quot;&gt;posts&lt;/code&gt; within a &lt;code class=&quot;highlighter-rouge&quot;&gt;category&lt;/code&gt; for a &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt;, only the &lt;code class=&quot;highlighter-rouge&quot;&gt;posts&lt;/code&gt; which have a &lt;code class=&quot;highlighter-rouge&quot;&gt;created_at&lt;/code&gt; in the current month are desired.&lt;/p&gt;

&lt;p&gt;A naive &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; only solution might look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;today&lt;/span&gt;
                         &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beginning_of_month&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;ss&quot;&gt;category: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;news&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;created_at &amp;gt;= ?&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sql&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;posts&quot;.* FROM &quot;posts&quot;  WHERE &quot;posts&quot;.&quot;user_id&quot; = 123 AND &quot;posts&quot;.&quot;category&quot; = &#39;news&#39; AND (created_at &amp;gt;= &#39;2016-03-01&#39; )&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This query will give the desired results but uses raw SQL. Using raw SQL is not always a bad practice, but in this case it seems unnecessary and could cause issue later.&lt;/p&gt;

&lt;h2 id=&quot;modelareltable&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Model.arel_table&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Every &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; model can access its underlying &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; representation with the &lt;code class=&quot;highlighter-rouge&quot;&gt;arel_table&lt;/code&gt; class method.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arel_table&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;Arel::Table:0x00000103ae7f00 @name=&quot;posts&quot;, ...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; table exposes each column of the underlying table. These columns provide many &lt;a href=&quot;https://github.com/rails/arel/blob/f50de54/lib/arel/predications.rb&quot;&gt;available methods&lt;/a&gt; used for comparison with either another column or scalar value.&lt;/p&gt;

&lt;p&gt;The same &lt;code class=&quot;highlighter-rouge&quot;&gt;Post&lt;/code&gt; query from above using its &lt;code class=&quot;highlighter-rouge&quot;&gt;arel_table&lt;/code&gt; looks like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beginning_of_month&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arel_table&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;news&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gteq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sql&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;posts&quot;.* FROM &quot;posts&quot;  WHERE (&quot;posts&quot;.&quot;user_id&quot; = 1234 AND &quot;posts&quot;.&quot;category&quot; = &#39;news&#39; AND &quot;posts&quot;.&quot;created_at&quot; &amp;gt;= &#39;2016-03-01&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After all the necessary conditions are applied to the &lt;code class=&quot;highlighter-rouge&quot;&gt;arel&lt;/code&gt; variable, it is given to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Post&lt;/code&gt; class via the &lt;code class=&quot;highlighter-rouge&quot;&gt;where&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;With this pure Ruby query generation, something looks a little different. Instead of:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2016-03-01&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The query has changed to:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;created_at&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2016-03-01&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This change points to one of the issues of the raw SQL approach: its inflexibility when dealing with multiple tables.&lt;/p&gt;

&lt;h2 id=&quot;join-resistance&quot;&gt;Join Resistance&lt;/h2&gt;

&lt;p&gt;Iterating on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Post&lt;/code&gt; query, it now needs to return the relevant &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;. If the original raw SQL solution was used the &lt;code class=&quot;highlighter-rouge&quot;&gt;user.created_at&lt;/code&gt; column and the &lt;code class=&quot;highlighter-rouge&quot;&gt;posts.created_at&lt;/code&gt; column would clash, resulting in an error:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;ss&quot;&gt;category: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;news&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;created_at &amp;gt;= ? &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;joins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; ActiveRecord::StatementInvalid: PG::AmbiguousColumn: ERROR:  column reference &quot;created_at&quot; is ambiguous&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The problem is clearly seen in the generated SQL:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;posts&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;users&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;users&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;id&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;user_id&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;user_id&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&quot;category&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;news&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2016-03-01&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Since PosgreSQL does not know which &lt;code class=&quot;highlighter-rouge&quot;&gt;created_at&lt;/code&gt; column to compare against this date, it can not fulfill the query.&lt;/p&gt;

&lt;p&gt;This problem does not exist in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; solution:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arel_table&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;news&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gteq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;joins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sql&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;posts&quot;.*, &quot;users.*&quot; FROM &quot;posts&quot; INNER JOIN &quot;users&quot; ON &quot;users&quot;.&quot;id&quot; = &quot;posts&quot;.&quot;user_id&quot; WHERE (&quot;posts&quot;.&quot;user_id&quot; = 1234 AND &quot;posts&quot;.&quot;category&quot; = &#39;news&#39; AND &quot;posts&quot;.&quot;created_at&quot; &amp;gt;= &#39;2016-03-01&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: The actual generated query has many column aliases in the select clause for the &lt;code class=&quot;highlighter-rouge&quot;&gt;includes&lt;/code&gt; behaviour but is irrelevant for these examples.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With each element specifying both table and column names, this query is still pure Ruby and &lt;code class=&quot;highlighter-rouge&quot;&gt;join&lt;/code&gt; friendly.&lt;/p&gt;

&lt;h2 id=&quot;advanced-selecting&quot;&gt;Advanced Selecting&lt;/h2&gt;

&lt;p&gt;Simple joins and comparison operators are useful but barely begin to explore the vast API contained within &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt;. An interesting feature that &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; provides is how to create and utilize &lt;strong&gt;C&lt;/strong&gt;ommon &lt;strong&gt;T&lt;/strong&gt;able &lt;strong&gt;E&lt;/strong&gt;xpressions (CTEs).&lt;/p&gt;

&lt;p&gt;A CTE is a temporary named result in an SQL database, derived from a &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; query. This derived result remains present in the scope for additional &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;INSERT&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;UPDATE&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;DELETE&lt;/code&gt; queries. CTEs can be thought of as alternatives to temporary tables, sub-queries, views, or other in-line user-defined functions.&lt;/p&gt;

&lt;h4 id=&quot;ask-find-all-posts-written-within-the-last-month-then-return-the-email-of-each-user-who-wrote-the-post&quot;&gt;Ask: Find all posts written within the last month, then return the email of each user who wrote the post.&lt;/h4&gt;

&lt;p&gt;Since no &lt;code class=&quot;highlighter-rouge&quot;&gt;Post&lt;/code&gt; data is required, this ask is a great candidate for a CTE. A new &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel::Table&lt;/code&gt; can be created to house the CTE and then the &lt;code class=&quot;highlighter-rouge&quot;&gt;join&lt;/code&gt; method on the &lt;code class=&quot;highlighter-rouge&quot;&gt;User.arel_table&lt;/code&gt; makes it accessible:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arel_table&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user_arel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arel_table&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;common_table_results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gteq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Arel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
              &lt;span class=&quot;ss&quot;&gt;:posts_last_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;composed_cte&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Arel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;As&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;common_table_results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;user_arel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;composed_cte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sql&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; WITH &quot;posts_last_month&quot; AS (SELECT &quot;posts&quot;.&quot;user_id&quot; FROM &quot;posts&quot; WHERE &quot;posts&quot;.&quot;created_at&quot; &amp;gt;= &#39;2016-03-01&#39;) SELECT &quot;users&quot;.&quot;email&quot; FROM &quot;users&quot; INNER JOIN &quot;posts_last_month&quot; ON &quot;users&quot;.&quot;id&quot; = &quot;posts_last_month&quot;.&quot;user_id&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;At first glance, this code can be a bit intimidating but it is actually quite simple. Both the &lt;code class=&quot;highlighter-rouge&quot;&gt;Post&lt;/code&gt; model and &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; model have had their underlying &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; representation referenced. Then, the CTE result is computed:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;common_table_results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post_arel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gteq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;beginning_of_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The most noticeable attribute here is the &lt;code class=&quot;highlighter-rouge&quot;&gt;project&lt;/code&gt; method. This method tells the query what to &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt;. Since only &lt;code class=&quot;highlighter-rouge&quot;&gt;user_ids&lt;/code&gt; are relevant in this CTE, that is all that is requested.&lt;/p&gt;

&lt;p&gt;Next, the actual CTE is created (in &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; representation only, not in the database):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Arel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
              &lt;span class=&quot;ss&quot;&gt;:posts_last_month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;composed_cte&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Arel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;As&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;common_table_results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;As&lt;/code&gt; class under the &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel::Nodes&lt;/code&gt; namespace is created and then fed into the end of the main query via the &lt;code class=&quot;highlighter-rouge&quot;&gt;with&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user_arel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;composed_cte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Again, since only the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; of the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; is desired, the &lt;code class=&quot;highlighter-rouge&quot;&gt;project&lt;/code&gt; method is used. The &lt;code class=&quot;highlighter-rouge&quot;&gt;join&lt;/code&gt; method is similar to the &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; method &lt;code class=&quot;highlighter-rouge&quot;&gt;joins&lt;/code&gt; but requires the &lt;code class=&quot;highlighter-rouge&quot;&gt;on&lt;/code&gt; clause to tell the query how to join the tables. Finally, the &lt;code class=&quot;highlighter-rouge&quot;&gt;with&lt;/code&gt; method receives the computed CTE representation and the query is successfully generated.&lt;/p&gt;

&lt;p&gt;To actually use this query, another helpful method on &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;find_by_sql&lt;/code&gt; can accept the full &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; representation, returning the desired &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; models with only the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column retrieved:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_by_sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;user_arel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cte_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;composed_cte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [#&amp;lt;User id: nil, email: &quot;foo@bar.com&quot;&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;why&quot;&gt;Why?&lt;/h2&gt;

&lt;p&gt;Like most tools, &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; may not be applicable in every situation. However, when used appropriately, it can make for some very well maintainable code that is resistant to unexpected failures. When dealing with multiple levels of an application stack, abstracting away complexities around their communication can help vastly simplify a codebase. &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; do a great job of insulating application developers from the nitty-gritty of database communication. Where &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; falls short, &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; is there to pick up the slack.&lt;/p&gt;

&lt;p&gt;For extremely specific or complex database interactions, using &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; may not be the correct choice, but should at least be evaluated. Only interacting with the lowest level necessary for a resource has many benefits. An &lt;code class=&quot;highlighter-rouge&quot;&gt;Arel&lt;/code&gt; solution to a problem has the potential to be more resilient to future changes.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Real Cost of Technical Debt</title>
   <link href="https://jakeyesbeck.com/2016/03/06/the-real-cost-of-technical-debt/"/>
   <updated>2016-03-06T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/03/06/the-real-cost-of-technical-debt</id>
   <content type="html">&lt;p&gt;Writing software is an iterative process. Rarely is software written and then never revisited. When this iteration occurs, a software engineer is presented with multiple options. Usually, a single objectively correct option is present but may not be chosen due to time constraints or other outside pressures. When shortcuts are taken to alleviate these external pressures, technical debt is often accrued.&lt;/p&gt;

&lt;h2 id=&quot;permit-today-pay-tomorrow&quot;&gt;Permit Today, Pay Tomorrow&lt;/h2&gt;

&lt;p&gt;Technical debt is referred to as such due to its similarities with financial debt. A credit card enables a person to complete a purchase they may not otherwise be able to, resulting in a bill to be paid by that person in the future: a debt. Technical debt is the same concept; a current feature or product is completed faster than previously possible at the cost of future work: a technical debt.&lt;/p&gt;

&lt;p&gt;If not apparent from name alone, technical debt is not a desired feature in a healthy software system. This debt can often appear benign, giving no cause for alarm or prompt resolution; however, I believe that thinking to be in error. Technical debt can severely damage a software application and may even cause its destruction.&lt;/p&gt;

&lt;h4 id=&quot;solution-communicate-the-importance-of-the-correct-approach&quot;&gt;Solution: Communicate the Importance of the Correct Approach&lt;/h4&gt;

&lt;p&gt;Open communication about why a solution might be slower to accomplish now, but result in a healthier system for the future can be very important. A conversation about the amount of technical debt a “fast” solution will generate might help reduce pressure.&lt;/p&gt;

&lt;h2 id=&quot;ongoing-overhead&quot;&gt;Ongoing Overhead&lt;/h2&gt;

&lt;p&gt;Left unchecked, technical debt can become a constant complexity or time increasing abscess for an otherwise healthy software application. Suddenly, every task that must interact with or touch technical debt affected code is not as simple as it should be. The “simple change” that a product team might request can have its scope increased due to technical debt overages.&lt;/p&gt;

&lt;p&gt;For example, we can assume that a typical web application decides that its new mobile friendly version should be a parallel implementation instead of investing time in making the existing experience responsive. This not DRY solution is immediately technical debt. When a new feature is to be added, it must be added in two distinct places instead of one. This decision might have been made due to the existing implementation having an amount of already unresolved technical debt, making it inflexible to change.&lt;/p&gt;

&lt;h4 id=&quot;solution-plan-for-overhead-reduction&quot;&gt;Solution: Plan for Overhead Reduction&lt;/h4&gt;

&lt;p&gt;To combat this problem, regular intervals of re-factoring and code cleanup should be inserted into a normal development flow. Making time to address technical debt can reduce a problem from an avalanche to a gentle dusting.&lt;/p&gt;

&lt;h2 id=&quot;re-factor-routines&quot;&gt;Re-factor Routines&lt;/h2&gt;

&lt;p&gt;To reduce technical debt, software must be re-factored to remove it and usually obtain the originally desired version of the code. These necessary changes, if not handled in a timely matter, can delay a future project or stop one in progress. Much like a bank charges interest for credit card bills, technical debt’s interest can result in application slowdowns, intermittent errors, or unusual edge cases until a re-factoring occurs.&lt;/p&gt;

&lt;p&gt;Continuing the mobile implementation example, if the two experiences are to be combined into a single code path, this combination might incur a significant amount of work. Tack on application uptime concerns and maintaining pleasant experiences for active end users, the previous credit granted by this technical debt has less and less value.&lt;/p&gt;

&lt;p&gt;On the other hand, if re-factoring is avoided for too long, the compounded technical debt interest can make feature development and iteration grind to a halt until addressed.&lt;/p&gt;

&lt;h4 id=&quot;solution-embrace-re-factoring-and-learn-something-new&quot;&gt;Solution: Embrace Re-Factoring and Learn Something New&lt;/h4&gt;

&lt;p&gt;Re-factoring code should not have the same negative connotation that technical debt has. Actually, re-factoring is a great time to try out new patterns and ideas. Since true re-factoring dictates that code adhere to the same contract it did before completion, it grants a level of safety and enables experimentation. Conducting these rewrites regularly can help reduce technical debt and grow a developer’s skill set.&lt;/p&gt;

&lt;h2 id=&quot;accessible-anti-patterns&quot;&gt;Accessible Anti-Patterns&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I can resist anything except temptation.”
          - Oscar Wilde&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The barrier for compromising standards when devising a solution weakens when it is routinely circumvented. As shortcuts become apparent, internal or external pressures to utilize these shortcuts might make them more attractive.&lt;/p&gt;

&lt;p&gt;Admittedly, not all problems can be solved without the accrual of technical debt; however, when it becomes the Status Quo for development, alarms should start sounding. Maintaining vigilance and respecting proper development practices are the responsibilities for the professional software engineer. Allowing one’s self or one’s team to slide the quality meter too far towards the “quick and easy” side will result in more technical debt now, more code to re-work and repair later.&lt;/p&gt;

&lt;h4 id=&quot;solution-keep-previous-technical-debt-payments-in-memory&quot;&gt;Solution: Keep Previous Technical Debt Payments in Memory&lt;/h4&gt;

&lt;p&gt;Human beings can be impulsive. To keep that inclination in check, remembering the cost of a previously dealt with bit of technical debt can help remind people the downsides of such solutions.&lt;/p&gt;

&lt;h2 id=&quot;inevitable-irregularity&quot;&gt;Inevitable Irregularity&lt;/h2&gt;

&lt;p&gt;Discipline is important when creating software applications able to stand the test of time. Having the discipline to push towards the reduction of technical debt inducing solutions can be difficult, but will result in a better system and brighter development future.&lt;/p&gt;

&lt;p&gt;Even the most bullish proponents of correct solutions may find themselves in some amount of technical debt. It is not always avoidable. At times, it can even be the correct path. When external pressures carry a large enough weight (like the survival of a company) it might be correct to cut corners and take on the risk of technical debt.&lt;/p&gt;

&lt;h4 id=&quot;solution-be-realistic&quot;&gt;Solution: Be Realistic&lt;/h4&gt;

&lt;p&gt;Technical debt will happen. When it does, leave notes for your future self to work with and remember that even the best in the business have cut a corner or two under pressure.&lt;/p&gt;

&lt;center&gt;
  &lt;img title=&quot;Maybe I haven&#39;t been to Iceland because I&#39;m busy dealing with YOUR crummy code.&quot; alt=&quot;technical debt future self&quot; src=&quot;https://imgs.xkcd.com/comics/future_self.png&quot; /&gt;
  &lt;a href=&quot;https://xkcd.com/1421/&quot;&gt;credit: xkcd&lt;/a&gt;
&lt;/center&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Spaceship &lt;=&gt; Operator</title>
   <link href="https://jakeyesbeck.com/2016/02/28/ruby-spaceship-operator/"/>
   <updated>2016-02-28T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/02/28/ruby-spaceship-operator</id>
   <content type="html">&lt;p&gt;Adhering to the law of trichotomy, the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; operator (sometimes called the “Spaceship Operator”) works by comparing two elements and returning a &lt;code class=&quot;highlighter-rouge&quot;&gt;-1&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt;. While the original mathematical criteria applies to only real numbers, many programming languages implement the law of trichotomy as a general comparison between equivalent types.&lt;/p&gt;

&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;/h2&gt;

&lt;p&gt;At first glance, the return value of the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; operator can be a bit confusing. A simple way to remember the significance of these return values is to break an expression down from left to right:&lt;/p&gt;

&lt;h3 id=&quot;section&quot;&gt;1. &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; –&amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;-1&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;if &lt;code class=&quot;highlighter-rouge&quot;&gt;a &amp;lt; b&lt;/code&gt;, then &lt;code class=&quot;highlighter-rouge&quot;&gt;-1&lt;/code&gt; is returned&lt;/p&gt;

&lt;h3 id=&quot;section-1&quot;&gt;2. &lt;code class=&quot;highlighter-rouge&quot;&gt;=&lt;/code&gt; –&amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;if &lt;code class=&quot;highlighter-rouge&quot;&gt;a = b&lt;/code&gt;, then &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt; is returned&lt;/p&gt;

&lt;h3 id=&quot;section-2&quot;&gt;3. &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; –&amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;if &lt;code class=&quot;highlighter-rouge&quot;&gt;a &amp;gt; b&lt;/code&gt;, then &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt; is returned&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; -1&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 0&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;sorting&quot;&gt;Sorting&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; operator can be used alone for comparison or its contract honored within a block following the &lt;code class=&quot;highlighter-rouge&quot;&gt;sort&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;By default, the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; operator behaves as described above:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [0, 1, 3, 3, 4, 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Following this pattern, it is easy to sort a list in reverse by swapping operand positions:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [8, 4, 3, 3, 1, 0]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;sort&lt;/code&gt; method is extendable beyond explicit use of the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; operator. A block passed to &lt;code class=&quot;highlighter-rouge&quot;&gt;sort&lt;/code&gt; must only return either &lt;code class=&quot;highlighter-rouge&quot;&gt;-1&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt; for sorting to work effectively.&lt;/p&gt;

&lt;p&gt;If the same list were to be ordered in odds then evens:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;odd?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [3, 3, 1, 4, 8, 0]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Also, since &lt;code class=&quot;highlighter-rouge&quot;&gt;-1&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt; are simple integers, creating compound &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; blocks is possible. If the same list were to be sorted odds then evens, with all odd and even numbers sorted in ascending order, it might look like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;odd?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;odd?&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# both are odd, default &amp;lt;=&amp;gt; behaviour is used&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# a &amp;lt; b&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# a is even&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;even?&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# both are even, default &amp;lt;=&amp;gt; behaviour is used&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# a &amp;gt; b&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [1, 3, 3, 0, 4, 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Far from elegant, this code effectively sorts the array of numbers first by odds to evens and then in ascending order.&lt;/p&gt;

&lt;h2 id=&quot;custom-methods&quot;&gt;Custom Methods&lt;/h2&gt;

&lt;p&gt;While thought of and generally referred to as an operator, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; is actually a method. Defined originally on &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;, any object has the opportunity to redefine this method to achieve custom sort behaviour.&lt;/p&gt;

&lt;p&gt;An example class, &lt;code class=&quot;highlighter-rouge&quot;&gt;Node&lt;/code&gt;, has a single attribute &lt;code class=&quot;highlighter-rouge&quot;&gt;value&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;By default, sorting an array of &lt;code class=&quot;highlighter-rouge&quot;&gt;Node&lt;/code&gt; objects does not produce the desired result:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; ArgumentError: comparison of Node with Node failed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, with a custom &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [#&amp;lt;Node: @value=10&amp;gt;, #&amp;lt;Node: @value=20&amp;gt;, #&amp;lt;Node: @value=30&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Boom! Custom sorting in the mix!&lt;/p&gt;

&lt;p&gt;Admittedly, this same behaviour is possible with the built in &lt;code class=&quot;highlighter-rouge&quot;&gt;sort_by&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [#&amp;lt;Node: @value=10&amp;gt;, #&amp;lt;Node: @value=20&amp;gt;, #&amp;lt;Node: @value=30&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;But, what happens when the &lt;code class=&quot;highlighter-rouge&quot;&gt;Node&lt;/code&gt; class wants to expose a sorting mechanism while removing its &lt;code class=&quot;highlighter-rouge&quot;&gt;value&lt;/code&gt; method? In that case, the &lt;code class=&quot;highlighter-rouge&quot;&gt;sort_by&lt;/code&gt; method would no longer be sufficient.&lt;/p&gt;

&lt;p&gt;Defining a custom &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; method also allows objects to include the &lt;code class=&quot;highlighter-rouge&quot;&gt;Comparable&lt;/code&gt; mixin effectively. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Comparable&lt;/code&gt; mixin provides the conventional comparison operators (&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&lt;/code&gt;, etc.).&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Comparable&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;250&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;node3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;between?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Comparable&lt;/code&gt; mixin provides very useful functionality that can easily turn a custom class into a sortable list element. As with most patterns in software, using the right tool at the right time is very important. It may not always be appropriate to write a custom comparison mechanism for a class, but when it is, the collaboration of &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;Comparable&lt;/code&gt; mixin is worth evaluating.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Four PostgreSQL Tips</title>
   <link href="https://jakeyesbeck.com/2016/02/21/four-postgresql-tips/"/>
   <updated>2016-02-21T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/02/21/four-postgresql-tips</id>
   <content type="html">&lt;p&gt;PostgreSQL is an open source object-relational database used to power many production web applications. While many web applications interact with relational databases through Object Relational Mappers (&lt;strong&gt;ORM&lt;/strong&gt;), direct SQL queries via a command line interface or graphical client are still common. When writing these queries, these four tips may come in handy.&lt;/p&gt;

&lt;p&gt;All examples will assume the presence of a simple users table:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;k&quot;&gt;Column&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;Type&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;---------------+-----------------------------
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;            &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;integer&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varying&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;last_name&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varying&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varying&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;without&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;zone&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;updated_at&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;without&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;zone&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varying&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;registered&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boolean&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;registered_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;without&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;zone&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Indexes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;&quot;users_pkey&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;finding-duplicate-rows&quot;&gt;1. Finding Duplicate Rows&lt;/h2&gt;

&lt;p&gt;A common mechanism for defending against duplicate rows in database tables are unique indexes. However, at the time of table creation, a unique index or two may have been forgotten. Duplicates in a table must be removed before a unique index may be added.&lt;/p&gt;

&lt;p&gt;A great way to detect duplicates in PostgreSQL is by using window functions. Window functions are similar to aggregates; but, instead of grouping rows for the response, it maintains each row’s individuality.&lt;/p&gt;

&lt;p&gt;Desired query: Find all duplicate &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; with the same &lt;code class=&quot;highlighter-rouge&quot;&gt;first_name&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;last_name&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt;, returning duplicate &lt;code class=&quot;highlighter-rouge&quot;&gt;ids&lt;/code&gt; only (do not return the oldest &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt;).&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ROW_NUMBER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OVER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PARTITION&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_row_number&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duplicates&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;duplicates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_row_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This query will identify all the rows of the &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table which share the same defined columns and return the primary key (&lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt;) of rows &lt;em&gt;after&lt;/em&gt; the first via the &lt;code class=&quot;highlighter-rouge&quot;&gt;duplicates.user_row_number &amp;gt; 1&lt;/code&gt; condition. The result of this query can then be fed into a &lt;code class=&quot;highlighter-rouge&quot;&gt;DELETE&lt;/code&gt; query to remove the duplicates.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;ROW_NUMBER()&lt;/code&gt; built-in function returns an incremented value assigned to each row that matches the criteria in the provided &lt;code class=&quot;highlighter-rouge&quot;&gt;OVER&lt;/code&gt; clause. This &lt;code class=&quot;highlighter-rouge&quot;&gt;OVER&lt;/code&gt; clause is followed by the window function: &lt;code class=&quot;highlighter-rouge&quot;&gt;PARTITION&lt;/code&gt;, which divides matching rows into groups or partitions using the columns or functions which follow it. Learn more about window functions at the &lt;a href=&quot;https://www.postgresql.org/docs/current/static/tutorial-window.html&quot;&gt;official PostgreSQL documentation page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;interval&quot;&gt;2. &lt;code class=&quot;highlighter-rouge&quot;&gt;interval&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Ever had to scope the results of a database query to a certain time range? So has every developer ever. Luckily, PostgreSQL provides a very readable convenience function: &lt;code class=&quot;highlighter-rouge&quot;&gt;interval&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If a rolling count of &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; sign ups in the last 24 hours is desired, the following query makes it possible:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;1 day&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;interval&lt;/code&gt; function accepts a variety of input types. Days, Hours, Minutes, Weeks, and more options &lt;a href=&quot;https://www.postgresql.org/docs/current/interactive/datatype-datetime.html&quot;&gt;are available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;interval&lt;/code&gt; subtraction can be used on any &lt;code class=&quot;highlighter-rouge&quot;&gt;timestamp&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&#39;2016-02-19 12:00:00&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;3 weeks&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;::&lt;/code&gt; notation casts the string &lt;code class=&quot;highlighter-rouge&quot;&gt;2016-02-19 12:00:00&lt;/code&gt; to a &lt;code class=&quot;highlighter-rouge&quot;&gt;timestamp&lt;/code&gt;, a requirement when manipulating time ranges with &lt;code class=&quot;highlighter-rouge&quot;&gt;interval&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;remote-query-execution&quot;&gt;3. Remote Query Execution&lt;/h2&gt;

&lt;p&gt;A very powerful feature of PostreSQL, and more specifically the &lt;code class=&quot;highlighter-rouge&quot;&gt;psql&lt;/code&gt; command line interface, is the ability to run remote queries. With the &lt;code class=&quot;highlighter-rouge&quot;&gt;--command&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;-c&lt;/code&gt; flag, a query may be passed to any PostgreSQL server and executed.&lt;/p&gt;

&lt;p&gt;A unique use for this feature is the ability to transfer a query’s results directly from one environment to another.&lt;/p&gt;

&lt;p&gt;An extensive analysis of the &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table for all &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; that signed up in January is requested. This analysis has the potential to be very taxing on a production database, resulting in adverse effects on end users. Additionally, no follower or read only database exists to alleviate this problem. Production data must be transfered to a local environment so that the analysis can run side effect free.&lt;/p&gt;

&lt;p&gt;To accomplish this, the &lt;code class=&quot;highlighter-rouge&quot;&gt;psql&lt;/code&gt; client has the ability to execute a query and return its result to &lt;code class=&quot;highlighter-rouge&quot;&gt;stdout&lt;/code&gt;. Conversely, file contents or query results from &lt;code class=&quot;highlighter-rouge&quot;&gt;stdin&lt;/code&gt; may also be read within the &lt;code class=&quot;highlighter-rouge&quot;&gt;psql&lt;/code&gt; client.&lt;/p&gt;

&lt;p&gt;Utilizing both aspects of this behaviour could look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;psql &amp;lt;REMOTE POSTGRESQL URL&amp;gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
-c &lt;span class=&quot;s2&quot;&gt;&quot;copy (
      SELECT *
      FROM users
      WHERE date_trunc(&#39;month&#39;, created_at) = &#39;2016-01-01&#39;
    ) to stdout&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
| psql &amp;lt;LOCAL POSTGRESQL DATABASE&amp;gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
-c &lt;span class=&quot;s2&quot;&gt;&quot;copy users from stdin&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As an alternative to &lt;code class=&quot;highlighter-rouge&quot;&gt;pg_dump&lt;/code&gt;, this pattern is a quick solution for loading specific data from one database to another.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;copy&lt;/code&gt; command comes in two variants: &lt;code class=&quot;highlighter-rouge&quot;&gt;copy&lt;/code&gt;, which will be run by the PostgreSQL backend (user “postgres”) and &lt;code class=&quot;highlighter-rouge&quot;&gt;\copy&lt;/code&gt; which runs as the current user. Depending on permissions and what &lt;code class=&quot;highlighter-rouge&quot;&gt;copy&lt;/code&gt; is attempting to do, one may be more appropriate than the other.&lt;/p&gt;

&lt;h2 id=&quot;referencing-columns-by-select-position&quot;&gt;4. Referencing Columns by &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; Position&lt;/h2&gt;

&lt;p&gt;If one were to issue a &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; query with a &lt;code class=&quot;highlighter-rouge&quot;&gt;GROUP BY&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;ORDER BY&lt;/code&gt; clause, the columns in these clauses can be referenced by their position in the &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;Desired query: Retrieve a count of all users which share the same &lt;code class=&quot;highlighter-rouge&quot;&gt;first_name&lt;/code&gt; and were &lt;code class=&quot;highlighter-rouge&quot;&gt;created_at&lt;/code&gt; on the same hour of the same day then order by the hour of creation and then &lt;code class=&quot;highlighter-rouge&quot;&gt;first_name&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;without-numeric-referencing&quot;&gt;Without numeric referencing&lt;/h4&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date_trunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hour&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date_trunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hour&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date_trunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hour&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This query will satisfy the request, returning an ordered list &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; data grouped by their &lt;code class=&quot;highlighter-rouge&quot;&gt;first_name&lt;/code&gt; and hour of the &lt;code class=&quot;highlighter-rouge&quot;&gt;created_at&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;with-numeric-referencing&quot;&gt;With numeric referencing&lt;/h4&gt;

&lt;p&gt;Starting with 1, each value in the &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; clause can be referenced by its numerical position. This can help reduce typos and copy pasting issues:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date_trunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hour&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As queries become more complicated with references or additional aggregate functions, numerical referencing becomes even more valuable.&lt;/p&gt;

&lt;h4 id=&quot;use-with-caution&quot;&gt;Use with Caution&lt;/h4&gt;

&lt;p&gt;While handy, referencing columns by their position is not always appropriate. Adding columns to the &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; statement can invalidate previous referencing and cause unwanted behaviour. Additionally, with a significantly large number of columns in a &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; statement, readability can suffer when referring to them solely by numbers.&lt;/p&gt;

&lt;p&gt;As with anything, the use of numerical referencing should be deliberate and thoughtful.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Threads and ActiveRecord Connections</title>
   <link href="https://jakeyesbeck.com/2016/02/14/ruby-threads-and-active-record-connections/"/>
   <updated>2016-02-14T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/02/14/ruby-threads-and-active-record-connections</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/images/ruby-threads-activerecord-connections.jpg&quot; alt=&quot;Ruby Threads ActiveRecord Connections&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Processing large data sets is a common problem faced by many production web applications. &lt;a href=&quot;https://jakeyesbeck.com/2015/08/09/how-to-process-large-data-sets-with-ruby/&quot;&gt;One solution&lt;/a&gt; is to divide the work amongst multiple processes and have each responsible for a single or significantly smaller batch of data. However, this solution is not without its problems. Machine provisioning limitations or financial barriers may invalidate this solution for a very large N.&lt;/p&gt;

&lt;p&gt;Within the same vein as “divide and conquer” exists another solution, one which requires far fewer parallel processes: &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;. In the Ruby programming language, a &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; is a built-in object for concurrent programming.&lt;/p&gt;

&lt;p&gt;Unlike independent processes, all Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; within the same process share memory, enabling each individual &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; to consume or process objects and elements from the same data store.&lt;/p&gt;

&lt;p&gt;For this example, a database will be queried, results manipulated and finally returned to same database via &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;first-pass&quot;&gt;First Pass&lt;/h2&gt;

&lt;p&gt;Given a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; model backed by a simple &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUsersTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:last_name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:validated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The problem to solve is fairly straight forward:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;All &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; records that are not already validated should be fetched and an external API hit with their email address for validation, then saved. If a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&#39;s&lt;/code&gt; email address is not valid, it should be removed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fast forwarding through time, it can be assumed that a completely serial solution has been written and deemed unsatisfactory. Then, during a second iteration, a bit of concurrent code was written:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserEmailValidator&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;validated: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_in_batches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;batch_size: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;validate_emails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;validate_emails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;threads&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;email_validator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EmailService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;email_validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;validate&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email_validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;invalid?&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;validated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;threads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The important pieces of this code are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;find_in_batches(batch_size: 30)&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;To cut down on memory allocation, only 30 &lt;code class=&quot;highlighter-rouge&quot;&gt;Users&lt;/code&gt; are fetched at one time. Each of these &lt;code class=&quot;highlighter-rouge&quot;&gt;Users&lt;/code&gt; have their email address validated in a separate &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;threads.map(&amp;amp;:join)&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;join&lt;/code&gt; method is used to make the program wait for all &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; to complete. If one &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; were to error out, some rescue and retry logic could be added to help.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Functionally adequate, this code should iterate over the entire set of &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; records, 30 at a time, and update them in parallel.&lt;/p&gt;

&lt;p&gt;However, actually running this code will point out a very serious limitation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The GIL in MRI Ruby prevents this code from ever running &lt;strong&gt;truly&lt;/strong&gt; parallel but since this code is input/output constrained, it does not make a difference.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;connection-accumulation&quot;&gt;Connection Accumulation&lt;/h2&gt;

&lt;p&gt;Moments after the above code runs for the first time, this error is seen:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ConnectionTimeoutError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;could&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obtain&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;within&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;000&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As it turns out, each &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; spawned had allocated its own connection to the database via &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;. Then, even after the &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; completed its work, the connection was not relinquished. Stale, idle connections began to accumulate within the Ruby process and before even 1000 &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; objects could be processed, the connection pool was empty.&lt;/p&gt;

&lt;p&gt;Presumably, right after the &lt;code class=&quot;highlighter-rouge&quot;&gt;self.validate_emails&lt;/code&gt; method completed for a batch of &lt;code class=&quot;highlighter-rouge&quot;&gt;Users&lt;/code&gt;, the process should have released those connections to be used for either the next batch of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; or other processes.&lt;/p&gt;

&lt;p&gt;Since this liberation of database connections did not happen automatically, it seems that we must intervene.&lt;/p&gt;

&lt;h2 id=&quot;pool-full-of-connections-then-we-dive-in-it&quot;&gt;Pool Full of Connections, then We Dive in it&lt;/h2&gt;

&lt;p&gt;To help &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; handle connection allocation and deallocation, the &lt;a href=&quot;https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html#method-i-with_connection&quot;&gt;with_connection&lt;/a&gt; block is used. &lt;code class=&quot;highlighter-rouge&quot;&gt;with_connection&lt;/code&gt; is a method that &lt;code class=&quot;highlighter-rouge&quot;&gt;yields&lt;/code&gt; a connection to a block, then returns that same connection to the pool when the block has completed.&lt;/p&gt;

&lt;p&gt;Basically, it ensures that the life cycle for a single database connection is only active within the block provided.&lt;/p&gt;

&lt;p&gt;To make sure this solution will work, it is imperative that the database connection pool in either &lt;code class=&quot;highlighter-rouge&quot;&gt;database.yml&lt;/code&gt; or in a connection initializer is set high enough.&lt;/p&gt;

&lt;p&gt;An example database.yml:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;postgresql&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;production_database&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With a pool large enough, a &lt;code class=&quot;highlighter-rouge&quot;&gt;with_connection&lt;/code&gt; block can be inserted around the pertinent code:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserEmailValidator&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;validated: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_in_batches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;batch_size: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;validate_emails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;validate_emails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;threads&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;connection_pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_connection&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;email_validator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EmailService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;email_validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;validate&lt;/span&gt;

          &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email_validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;invalid?&lt;/span&gt;

          &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;validated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;

          &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;threads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Running this very deliberate connection handling process now ensures that no more than 30 connections are claimed. Each &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; will connect to the database with one single connection and the &lt;code class=&quot;highlighter-rouge&quot;&gt;with_connection&lt;/code&gt; block will return that connection to the predefined pool upon completion.&lt;/p&gt;

&lt;p&gt;With the addition of this necessary connection pruning, the great &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; email validation effort can complete. Depending on the size of the data set and machines available, the 30 per batch limit could be easily increased, resulting in greater validation speed.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;database.yml&lt;/code&gt; configuration should have a pool size of equal to or greater than the number of &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; spawned. If 100 &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; objects needed to be processed at once, the pool should be &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;= 100&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h2&gt;

&lt;p&gt;Handling database connections and using raw &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt; this explicitly can make some developers uncomfortable. Luckily, a few great libraries have been written to alleviate this problem.&lt;/p&gt;

&lt;p&gt;In a previous post, &lt;a href=&quot;https://jakeyesbeck.com/2016/01/10/how-to-parallelize-ruby-http-requests/#enter-em-synchrony&quot;&gt;EM Synchrony&lt;/a&gt; was utilized to make parallel HTTP requests. It also has the ability to parallelize &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; reading and writing without consuming excess database connections.&lt;/p&gt;

&lt;p&gt;Another helpful library quickly becoming the most popular concurrency library is &lt;a href=&quot;https://github.com/ruby-concurrency/concurrent-ruby&quot;&gt;concurrent-ruby&lt;/a&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;concurrent-ruby&lt;/code&gt; library provides convenient models for dealing with futures, promises and other parallelization data structures. However, the same &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; connections issues will occur with concurrent ruby objects as with plain old &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, this code has been written for the sake of making a point. There are many ways to solve a problem and this is simply one of them.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Remove a Column with Zero Downtime in Ruby on Rails</title>
   <link href="https://jakeyesbeck.com/2016/02/07/how-to-remove-a-column-with-zero-downtime-in-ruby-on-rails/"/>
   <updated>2016-02-07T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/02/07/how-to-remove-a-column-with-zero-downtime-in-ruby-on-rails</id>
   <content type="html">&lt;p&gt;For a production Ruby on Rails application, uptime is paramount. Altering the structure of an application’s persistence layer is an operation that competes directly with uptime. Specifically, removing a table column within a relational database causes issues with the &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; ORM (the default relational mapping within a Ruby on Rails application).&lt;/p&gt;

&lt;p&gt;However, this particular pain point has been removed as of &lt;strong&gt;Ruby on Rails 4.0.0&lt;/strong&gt;, saving developers a lot of headache and greatly reducing the need for structural change coordination.&lt;/p&gt;

&lt;h2 id=&quot;old-and-busted&quot;&gt;Old and Busted&lt;/h2&gt;

&lt;p&gt;To demonstrate the problem, a simple &lt;strong&gt;Ruby on Rails 3.2&lt;/strong&gt; application is created with a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; model:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Supporting the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; model is a PostgreSQL database table created with a migration:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:last_name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To ensure this application has as close to 100% uptime as possible, it can be assumed that it is behind some kind of pre-loader. As in, when code is deployed, existing requests are given time to complete before new requests are shepherded over to the new version of the code.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;Ruby on Rails 3.2&lt;/strong&gt; application, a problem will arise when a column is removed from the database and the ORM does not have time to restart. In this case, even the pre-loader will not save an application from throwing an error about the missing column.&lt;/p&gt;

&lt;p&gt;To emulate this problem, a rails console is run in the &lt;code class=&quot;highlighter-rouge&quot;&gt;production&lt;/code&gt; environment and a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; is created:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;RACK_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;production&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rails&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;console&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;User id: 1, first_name: &quot;test&quot;, last_name: &quot;test&quot;, email nil, created_at: &quot;2016-02-07 21:03:26&quot;, updated_at: &quot;2016-02-07 21:03:26&quot;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In parallel, the &lt;code class=&quot;highlighter-rouge&quot;&gt;psql&lt;/code&gt; command line client is used to connect to the same &lt;code class=&quot;highlighter-rouge&quot;&gt;production&lt;/code&gt; database used by this server, all still running &lt;strong&gt;locally&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Within this &lt;code class=&quot;highlighter-rouge&quot;&gt;psql&lt;/code&gt; prompt, the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column from the &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table will be removed &lt;em&gt;while&lt;/em&gt; the production console is still running:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;psql&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app_production&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;psql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COLUMN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Jumping back to the &lt;code class=&quot;highlighter-rouge&quot;&gt;RACK_ENV=production rails console&lt;/code&gt;, another &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; creation attempt results in an error:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test2&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test2&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; PG::UndefinedColumn: ERROR:  column &quot;email&quot; of relation &quot;users&quot; does not exist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Kaboom! Rails attempts to save a new record to the &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table and populate the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column even though it was never specified to do so.  Seeing as this is not new behaviour, surely someone has come up with a solution to this problem that does not require downtime.&lt;/p&gt;

&lt;h2 id=&quot;yesterdays-jam&quot;&gt;Yesterday’s Jam&lt;/h2&gt;

&lt;p&gt;As it turns out, &lt;a href=&quot;https://blog.codeship.com/rails-migrations-zero-downtime/&quot;&gt;a few&lt;/a&gt; different &lt;a href=&quot;https://www.codinginthecrease.com/news_article/show/85364?referrer_id=&quot;&gt;blog posts&lt;/a&gt; have been written about the solution to this very problem.&lt;/p&gt;

&lt;p&gt;The TL;DR of these posts is that a multiple phase solution is required under the given circumstances:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. Write code that `rejects` the column to remove
2. Deploy
3. Write migration to remove the column
4. Deploy + Migrate
5. Write code to remove the column `rejection`
6. Deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Phew! Three deploys and presumably three code reviews later, the column is finally removed. Assuming a system is built with continuous deployment guarded by a continuous integration suite, this whole process could take the better part of a work day in order to accomplish such a simple task.&lt;/p&gt;

&lt;p&gt;Even worse, if an application has scheduled weekly deploys where only one deployment can happen per week, then this column will linger for three whole weeks. That is just absurd, what kind of barbarians can live this way?&lt;/p&gt;

&lt;h2 id=&quot;new-hotness&quot;&gt;New Hotness&lt;/h2&gt;

&lt;p&gt;Luckily, the incredible people who maintain and create features for the Ruby on Rails framework saw this behaviour and decided to correct it. As of a very influential commit during the beta release of &lt;strong&gt;Ruby on Rails 4.0.0&lt;/strong&gt;, the framework does not aggressively attempt to populate attributes not specified during creation or update.&lt;/p&gt;

&lt;p&gt;To prove this, a new &lt;strong&gt;Ruby on Rails 4.0.0&lt;/strong&gt; application is made with the exact same structure as above.&lt;/p&gt;

&lt;p&gt;Then, the same production console is created along with a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;RACK_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;production&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rails&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;console&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;User id: 1, first_name: &quot;test&quot;, last_name: &quot;test&quot;, email nil, created_at: &quot;2016-02-07 22:09:49&quot;, updated_at: &quot;2016-02-07 22:09:49&quot;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Again, in parallel, a &lt;code class=&quot;highlighter-rouge&quot;&gt;psql&lt;/code&gt; client is initialized for the &lt;code class=&quot;highlighter-rouge&quot;&gt;production&lt;/code&gt; environment database.&lt;/p&gt;

&lt;p&gt;Within this prompt, the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column on the &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table is removed:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;psql&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app_production&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;psql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COLUMN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And finally, a new user is created in the still running &lt;code class=&quot;highlighter-rouge&quot;&gt;RACK_ENV=production rails console&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test2&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test2&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;User id: 2, first_name: &quot;test2&quot;, last_name: &quot;test2&quot;, email nil, created_at: &quot;2016-02-07 22:13:18&quot;, updated_at: &quot;2016-02-07 22:13:18&quot;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Unlike before, the second insertion into the &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt; table worked wonderfully, despite the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column’s removal.&lt;/p&gt;

&lt;p&gt;As shown, the in memory representation of the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class still has the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; attribute. The &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; object’s representation has not been reloaded, it simply just does not care about the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column when writing to the database.&lt;/p&gt;

&lt;p&gt;The fact that the ORM does not specifically reload when writing to a table points out an interesting detail. It means that for this solution to fully work, the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column must not be referenced at all.&lt;/p&gt;

&lt;p&gt;With this new found behaviour, the previous six step incantation comprised of three separate deployments can be reduced to three steps in total and just one deployment:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. Remove references to column and write migration
2. Deploy
3. Once requests completely use new code, migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Wunderbar! The &lt;code class=&quot;highlighter-rouge&quot;&gt;reject&lt;/code&gt; and deploy pattern is no longer necessary. Further more, development teams suffering within weekly scheduled deploys can achieve their desired results within a single iteration.&lt;/p&gt;

&lt;h2 id=&quot;what-changed&quot;&gt;What Changed?&lt;/h2&gt;

&lt;p&gt;Unfortunately, the amazing change responsible for this vast improvement regarding Ruby on Rails column removal did not receive the attention is deserves. Many blog posts and guides were written about how to circumvent the older 3.2 behaviour, but when looking for information about this modern implementation, resources were scarce.&lt;/p&gt;

&lt;p&gt;After reading through a very large amount of change logs and coming up empty, a &lt;a href=&quot;https://jakeyesbeck.com/2015/10/25/how-to-traverse-foreign-ruby-code/&quot;&gt;bit of previous wisdom&lt;/a&gt; was utilized in order to track down the commit responsible.&lt;/p&gt;

&lt;p&gt;The first step is to identify the offending code in 3.2. This way, the 4.0.0 version of the code can be analyzed, the discrepancy identified and the git revision responsible brought to light.&lt;/p&gt;

&lt;p&gt;After some &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; insertions and utilization of the &lt;code class=&quot;highlighter-rouge&quot;&gt;caller&lt;/code&gt; array, the offending code was traced to &lt;a href=&quot;https://github.com/rails/rails/blob/v3.2.18/activerecord/lib/active_record/attribute_methods.rb#L244&quot;&gt;lib/active_record/attribute_methods.rb:244&lt;/a&gt; (formatted for readability):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;arel_attributes_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include_primary_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;include_readonly_attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;attribute_names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;arel_table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arel_table&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;attribute_names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column_for_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include_primary_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;include_readonly_attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;readonly_attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;serialized_attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;vi&quot;&gt;@attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;serialized_value&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# FIXME: we need @attributes to be used consistently.&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# If the values stored in @attributes were already type&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# casted, this code could be simplified&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;read_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;While a little lengthy, the most obvious thing to note about this method is that its signature is comprised of entirely optional variables. Most notably, the final optional parameter, &lt;code class=&quot;highlighter-rouge&quot;&gt;attribute_names&lt;/code&gt;, defaults to &lt;code class=&quot;highlighter-rouge&quot;&gt;@attributes.keys&lt;/code&gt; which is the list of attributes for the given model.&lt;/p&gt;

&lt;p&gt;In this case, the result of &lt;code class=&quot;highlighter-rouge&quot;&gt;@attributes.keys&lt;/code&gt; is the complete list of keys for a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;[&#39;id&#39;, &#39;first_name&#39;, &#39;last_name&#39;, &#39;email&#39;, &#39;updated_at&#39;, &#39;created_at&#39;]&lt;/code&gt;. Most notably, the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; attribute is present, regardless of the fact that it was not given a value to insert. This means that by default, any &lt;code class=&quot;highlighter-rouge&quot;&gt;create&lt;/code&gt; call will write to the &lt;code class=&quot;highlighter-rouge&quot;&gt;email&lt;/code&gt; column without hesitation (just as previously observed).&lt;/p&gt;

&lt;p&gt;While default behaviour can emit a code smell, it is only dangerous if it is used unknowingly. Since the parameter to determine &lt;code class=&quot;highlighter-rouge&quot;&gt;attribute_names&lt;/code&gt; is available, chances are the caller of this method does indeed specify them, right?&lt;/p&gt;

&lt;p&gt;Unfortunately, no:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attributes_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arel_attributes_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;new_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unscoped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attributes_values&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_id&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;primary_key&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;IdentityMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;IdentityMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enabled?&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@new_record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here, in &lt;a href=&quot;https://github.com/rails/rails/blob/v3.2.18/activerecord/lib/active_record/persistence.rb#L364&quot;&gt;lib/active_record/persistence.rb:364&lt;/a&gt; lies the method responsible for calling &lt;code class=&quot;highlighter-rouge&quot;&gt;arel_attributes_values&lt;/code&gt;. Since it does not specify the list of attributes, the default behaviour prevails and all known attributes are returned.&lt;/p&gt;

&lt;h2 id=&quot;the-big-fix&quot;&gt;The Big Fix&lt;/h2&gt;

&lt;p&gt;On a glorious Friday afternoon (probably) Jon Leighton made &lt;a href=&quot;https://github.com/rails/rails/commit/144e8691&quot;&gt;the commit&lt;/a&gt; which changed how people thought about column removal in Ruby on Rails.&lt;/p&gt;

&lt;p&gt;The change enabled the concept of &lt;code class=&quot;highlighter-rouge&quot;&gt;partial_writes&lt;/code&gt;. This pattern used the exiting &lt;code class=&quot;highlighter-rouge&quot;&gt;changed&lt;/code&gt; hash present in every &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; model. The &lt;code class=&quot;highlighter-rouge&quot;&gt;changed&lt;/code&gt; hash is manipulated as a model has attributes assigned to it.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/rails/rails/blob/v4.0.0/activerecord/lib/active_record/attribute_methods/dirty.rb#L77&quot;&gt;lib/active_record/attribute_methods/dirty.rb:77&lt;/a&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;partial_writes&lt;/code&gt; is used:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;partial_writes?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys_for_partial_write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Serialized attributes should always be written in case they&#39;ve been&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# changed in place.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;keys_for_partial_write&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;changed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;serialized_attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Before delegating to the same &lt;code class=&quot;highlighter-rouge&quot;&gt;persistence.rb#create&lt;/code&gt; method, only the attributes present in the &lt;code class=&quot;highlighter-rouge&quot;&gt;changed&lt;/code&gt; hash (along with any serialized attributes) will be used in subsequent insert queries.&lt;/p&gt;

&lt;p&gt;Included in the February 2013 beta release of &lt;strong&gt;Ruby on Rails 4.0.0&lt;/strong&gt;, this code enables a much more pleasant experience than the older work around. In fact, the author even pointed out this behaviour in his commit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When inserting new records, only the fields which have been changed from the defaults will actually be included in the INSERT statement. The other fields will be populated by the database.&lt;/p&gt;

  &lt;p&gt;This is more efficient, and also means that it will be safe to remove database columns without getting subsequent errors in running app processes (so long as the code in those processes doesn’t contain any references to the removed column).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;unshackled&quot;&gt;Unshackled&lt;/h2&gt;

&lt;p&gt;While this patch to the Ruby on Rails framework may not make every situation easier, it certainly reduces both cognitive and implementation overhead for many developers.&lt;/p&gt;

&lt;p&gt;For more automated systems utilizing continuous deployment, two deployments may still be necessary since code running on old processes (within some sort of pre loader) will not be able to handle the column removal.&lt;/p&gt;

&lt;p&gt;The deployment process for such a system may look more like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. Remove references to column
2. Deploy
3. Write migration to drop column
4. Deploy and migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Databases that power web applications are powerful and oddly fragile beasts. Manipulating these beasts while maintaining superb end user experiences requires one to constantly be learning. Hopefully with this behaviour, one more thing can be crossed off the check list of “things to remember when manipulating the database” and we can all just get back to work.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nine Months of Commits</title>
   <link href="https://jakeyesbeck.com/2016/01/30/nine-months-of-commits/"/>
   <updated>2016-01-30T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/01/30/nine-months-of-commits</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/280_day_streak.png&quot; alt=&quot;280 days of commits&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It is hard to believe that already nine months have passed since the onset of my &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt;. In these past nine months, I have experienced a wide range of new aspects of open source development. This has truly been an eye opening experience, with many facets I doubt I would have experienced otherwise.&lt;/p&gt;

&lt;h2 id=&quot;confidence&quot;&gt;Confidence&lt;/h2&gt;

&lt;p&gt;An unexpected and fortuitous side effect of my Year of Commits has manifested as a significant boost in my overall coding confidence. Confidence is a very important aspect of anyone’s life. Without confidence, a person may place objectives out of reach or deem them too arduous to achieve. Believing in one’s self and having the confidence to stand up when knocked down is a trait that carries a lot of weight, especially when writing software.&lt;/p&gt;

&lt;p&gt;Writing software can be a very subjective endeavor. Especially in languages like Ruby, there are many solutions to the same problem. These subtle differences can spark myriad conversations or criticisms of a person’s code. For those fortunate enough to write code for a living, think back to the times a pull request saw the most attention and accrued the most comments. Chances are, those comments pointed out style choice discrepancies or “we do not do it that way” assertions.&lt;/p&gt;

&lt;p&gt;Maintaining a steady level of confidence in the midst of such feedback is paramount. I am lucky enough to have received feedback from many different people in many different situations. This feedback and perspective help inoculate a developer and encourage them to remember &lt;a href=&quot;https://jakeyesbeck.com/2015/06/14/you-are-not-your-code/&quot;&gt;they are not their code&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;github-issues&quot;&gt;Github Issues&lt;/h2&gt;

&lt;p&gt;Another exciting event since my last &lt;a href=&quot;https://jakeyesbeck.com/2015/11/01/six-months-of-commits/&quot;&gt;year of commits update&lt;/a&gt; pertains to Github issues. Github is a fantastic piece of software responsible for managing git repositories and enabling collaboration amongst developers. An issue may be opened by anyone with a Github account on any public repository of their choosing. These issues have been the primary avenue I have used to find which projects need help and what I can do to help them.&lt;/p&gt;

&lt;p&gt;My excitement stems from the fact that, for the first time since I started Year of Commits, other developers have engaged with one of my projects (&lt;a href=&quot;https://github.com/yez/passages&quot;&gt;passages&lt;/a&gt;) and submitted some issues! Having consumers of software one builds is a great feeling. An even greater feeling is when those people care enough to submit issues they think can better the project.&lt;/p&gt;

&lt;p&gt;Becoming part of the open source community was a goal of this endeavor and I am thrilled to have taken my first few steps towards accomplishing that goal.&lt;/p&gt;

&lt;h2 id=&quot;code-discovery&quot;&gt;Code Discovery&lt;/h2&gt;

&lt;p&gt;Practice makes perfect. When reading code you did not write, knowing where to start and identifying patterns in code organization helps a great deal. Since the goal of Year of Commits was to contribute to my own &lt;strong&gt;and&lt;/strong&gt; other people’s code, I have been reading &lt;em&gt;a lot&lt;/em&gt; of code that I did not write. This has been a fantastic learning experience for me. At a typical software engineering job, coworkers’ code starts to blend styles and eventually become fairly homogeneous.&lt;/p&gt;

&lt;p&gt;By reading code written by many different people, new patterns and styles add a level of depth to code grokking that is hard to replicate in other ways. I came to appreciate this accidentally discovered benefit of Year of Commits so much, &lt;a href=&quot;https://jakeyesbeck.com/2015/10/25/how-to-traverse-foreign-ruby-code/&quot;&gt;I wrote a whole post describing the process for foreign code traversal.&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-home-stretch&quot;&gt;The Home Stretch&lt;/h2&gt;

&lt;p&gt;Year of Commits ends in April of 2016. Between now and then, I hope to learn even more about the open source software ecosystem and community. This project has had an incredibly positive affect on my life and I would prescribe something similar to anyone interested. My only goal between now and April is to have made a real contribution to a high visibility project.&lt;/p&gt;

&lt;p&gt;The positive feedback I have received about this blog and the work that I have been doing helps make this easy. I would like to say thank you again to everyone on this journey with me.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Private Class Methods</title>
   <link href="https://jakeyesbeck.com/2016/01/24/ruby-private-class-methods/"/>
   <updated>2016-01-24T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/01/24/ruby-private-class-methods</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/images/ruby-private-class-methods.jpg&quot; alt=&quot;Ruby Private Class Methods&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the Ruby programming language, defined methods come in two variants: instance methods and class methods. Instance methods are available after an object has been initialized, creating an instance. Class methods, on the other hand, are available without creating an instance of the class they are defined upon.&lt;/p&gt;

&lt;p&gt;Ruby methods can vary in visibility. Public methods are available in any context, while private methods’ availability is restricted within the instance of a class and its descendants. A third visibility scope, protected, behaves similarly to private methods, but protected methods can be called by other instances of the same class.&lt;/p&gt;

&lt;p&gt;For a quick refresher, public and private instance methods look like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_trick&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;woof woof&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When the public method is called:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do_trick&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; woof woof&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And the private method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; NoMethodError: private method `bark&#39; called for &amp;lt;Dog&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Private class methods might not be as common as private instance methods, but they still have their place. For instance, a class method may require internal helper methods to complete its function. Whatever the reason, defining private class methods has value but is not always intuitive.&lt;/p&gt;

&lt;p&gt;This example &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class needs to maintain a list of &lt;code class=&quot;highlighter-rouge&quot;&gt;tricks&lt;/code&gt; that will be used &lt;strong&gt;within&lt;/strong&gt; the other public class methods. This list should not be accessible to any callers outside the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class.&lt;/p&gt;

&lt;h2 id=&quot;the-wrong-way&quot;&gt;The wrong way&lt;/h2&gt;

&lt;p&gt;A first pass at writing the private &lt;code class=&quot;highlighter-rouge&quot;&gt;tricks&lt;/code&gt; method could look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:roll_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, when testing the visibility of the &lt;code class=&quot;highlighter-rouge&quot;&gt;tricks&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [:bark, :roll_over, :fetch]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Uh oh, no error was thrown indicating a that a private method was called, this method is completely public.&lt;/p&gt;

&lt;h2 id=&quot;why&quot;&gt;Why?&lt;/h2&gt;

&lt;p&gt;The reason that the above code did not produce a private method has to do with Ruby’s object hierarchy, interactions amongst  internal classes, instances of those classes, and eigenclasses. A detailed write up about how Ruby’s objects work with one another can be found in a &lt;a href=&quot;https://jakeyesbeck.com/2015/08/23/ruby-objects/&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When defining methods in a class, the default context and the context introduced by the &lt;code class=&quot;highlighter-rouge&quot;&gt;self.&lt;/code&gt; method declaration are distinct.&lt;/p&gt;

&lt;p&gt;The private method scope can not be used in the above way as it does not handle the context change between methods defined on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class and defined within &lt;code class=&quot;highlighter-rouge&quot;&gt;self&lt;/code&gt; context.&lt;/p&gt;

&lt;p&gt;So what are the alternatives?&lt;/p&gt;

&lt;h2 id=&quot;class--self&quot;&gt;1. &lt;code class=&quot;highlighter-rouge&quot;&gt;class &amp;lt;&amp;lt; self&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;One alternative way to define class methods on an object is to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;class &amp;lt;&amp;lt; self&lt;/code&gt; syntax. This syntax opens an eigenclass for the supplied argument. In this example, &lt;code class=&quot;highlighter-rouge&quot;&gt;self&lt;/code&gt; within the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class will open the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&#39;s&lt;/code&gt; eigenclass.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:roll_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;One thing to note is that when defining methods like this, the declaration has changed from &lt;code class=&quot;highlighter-rouge&quot;&gt;def self.tricks&lt;/code&gt; to simply &lt;code class=&quot;highlighter-rouge&quot;&gt;def tricks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, the private scope is preserved and expected behaviour is achieved:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; NoMethodError: private method `tricks&#39; called for Dog:Class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;modules&quot;&gt;2. Modules&lt;/h2&gt;

&lt;p&gt;Modules in ruby are collections of methods and constants. These collections can be used as encapsulation tools or, in this case, alternatives to defining public and private class methods.&lt;/p&gt;

&lt;p&gt;When a class &lt;code class=&quot;highlighter-rouge&quot;&gt;extends&lt;/code&gt; a module, all the methods within that module become class methods on the subject class*. This pattern can be used to define the &lt;code class=&quot;highlighter-rouge&quot;&gt;tricks&lt;/code&gt; method on &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*Note: This only pertains to methods defined in a “typical sense” any &lt;code class=&quot;highlighter-rouge&quot;&gt;def self.&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;def Dog.&lt;/code&gt; method definitions in a module do not automatically become class methods in the same way when &lt;code class=&quot;highlighter-rouge&quot;&gt;extended&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ClassMethods&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:roll_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ClassMethods&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; NoMethodError: private method `tricks&#39; called for Dog:Class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A benefit of this approach is readability. The module named &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassMethods&lt;/code&gt;, which is contained and thus encapsulated by the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class, is the clear home for all desired class methods.&lt;/p&gt;

&lt;p&gt;Visibility modifiers like &lt;code class=&quot;highlighter-rouge&quot;&gt;private&lt;/code&gt; behave accordingly and a simple &lt;code class=&quot;highlighter-rouge&quot;&gt;extend&lt;/code&gt; at the bottom of the module definition brings it all together.&lt;/p&gt;

&lt;h2 id=&quot;privateclassmethod&quot;&gt;3. &lt;code class=&quot;highlighter-rouge&quot;&gt;private_class_method&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;A third approach is to use the built in method &lt;code class=&quot;highlighter-rouge&quot;&gt;Module#private_class_method&lt;/code&gt;. This method’s purpose is to change the visibility of &lt;strong&gt;existing&lt;/strong&gt; class methods.&lt;/p&gt;

&lt;p&gt;Unlike the other two solutions, this one does not require a different style of method definition from the incorrect solution:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:roll_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;private_class_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:tricks&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; NoMethodError: private method `tricks&#39; called for Dog:Class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This method can also be in-lined during the class’ method definition:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;private_class_method&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:roll_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tricks&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; NoMethodError: private method `tricks&#39; called for Dog:Class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If a single class method must be private and saving lines is very important, this style might be applicable; but, it certainly sacrifices a level of readability.&lt;/p&gt;

&lt;p&gt;A major strength of &lt;code class=&quot;highlighter-rouge&quot;&gt;private_class_method&lt;/code&gt; is its explicitness. Unlike the other approaches, this one does not require a special module definition or method definition context switching.&lt;/p&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;

&lt;p&gt;The aforementioned solutions will get the job done but might not answer lingering questions about &lt;em&gt;why&lt;/em&gt; things work the way they do. A few great articles on &lt;a href=&quot;https://madebydna.com/all/code/2011/06/24/eigenclasses-demystified.html&quot;&gt;the ruby eigenclass&lt;/a&gt; and &lt;a href=&quot;https://junichiito.blogspot.com/2012/03/matz-answers-why-ruby-lets-sub-classes.html&quot;&gt;Matz’s thoughts on Ruby method design&lt;/a&gt; should help paint a more concise picture of why Ruby’s private class method definition is complex.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Contributing to Open Source in 7 Steps</title>
   <link href="https://jakeyesbeck.com/2016/01/17/contributing-to-open-source-in-7-steps/"/>
   <updated>2016-01-17T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/01/17/contributing-to-open-source-in-7-steps</id>
   <content type="html">&lt;p&gt;Making contributions to open source repositories is a great way to give back to the community. Open source software has a rich history and is a crucial component in many successful software applications. Most open source projects are maintained by either one or many developers for free. Since “free” is not usually the price of food and shelter, these maintainers are not available to work on their projects at all hours, most of them have day jobs so they can eat and buy clothing.&lt;/p&gt;

&lt;p&gt;To help keep open source projects up to date and bug free, members of the community regularly contribute a portion of their own free time. Since the start of the &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt; project, I have made quite a few contributes to open source software and distilled the process down to these seven basic steps.&lt;/p&gt;

&lt;h2 id=&quot;find-a-repository-that-has-some-issues&quot;&gt;1. Find a repository that has some issues&lt;/h2&gt;

&lt;p&gt;A great way to get a foot in the door in an open source repository is by solving one of its open issues. A project is much more likely to accept code that addresses an open issue as opposed to code that is added “just because”. Open issues are either bugs or feature requests and are tracked on Github.&lt;/p&gt;

&lt;p&gt;Some really great tools exist for exploring Github’s vast index of repositories for relevant projects. &lt;a href=&quot;https://www.codetriage.com/&quot;&gt;CodeTriage&lt;/a&gt; is one of these &lt;strong&gt;awesome&lt;/strong&gt; tools. CodeTriage enables a user to narrow down Github’s list of repositories by programming language. CodeTriage has a very nice UI, ordering a very large amount of Github projects in descending count of open issues.&lt;/p&gt;

&lt;p&gt;Alternatively, Github has their own tooling around discovering projects with their &lt;a href=&quot;https://github.com/explore&quot;&gt;explore feature&lt;/a&gt;. Trending repositories from this week or this month are available on a per programming language basis. The explore feature is great for popular projects but exposes far fewer projects than CodeTriage.&lt;/p&gt;

&lt;p&gt;To demonstrate a typical contribution’s life cycle, the &lt;a href=&quot;https://github.com/covermymeds/fetching-gem&quot;&gt;fetching-gem&lt;/a&gt; project has been chosen.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;fetching-gem&lt;/code&gt; library is a convenience Ruby library for accessing elements of nested hashes and arrays with dot notation and noisy feedback.&lt;/p&gt;

&lt;p&gt;Recently, the &lt;code class=&quot;highlighter-rouge&quot;&gt;fetching-gem&#39;s&lt;/code&gt; issues page had a feature request: “Make the library compatible with the &lt;a href=&quot;https://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-first&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable#first(n)&lt;/code&gt; behaviour&lt;/a&gt;”:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/find_issue.png&quot; alt=&quot;Find Issue&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;read-the-contributing-guidelines&quot;&gt;2. Read the contributing guidelines&lt;/h2&gt;

&lt;p&gt;Before starting work on a project, make sure that the contribution guidelines of the project have been met. Some more popular repositories have very explicit rules about the number of commits per patch, the logical grouping of those commits, and even commit message style concerns.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/covermymeds/fetching-gem#contributing&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;fetching-gem&#39;s&lt;/code&gt; contribution guidelines&lt;/a&gt; are very simple, it merely instructs that a fork should be made and then a pull request from the forked repository should be made.&lt;/p&gt;

&lt;h2 id=&quot;fork-it&quot;&gt;3. Fork it&lt;/h2&gt;

&lt;p&gt;Obtaining a copy of a project’s code is crucial when trying to make a contribution. In Github, the act of &lt;a href=&quot;https://help.github.com/articles/fork-a-repo/&quot;&gt;forking a repository&lt;/a&gt; creates a copy of the repository. This copy may be altered until the feature is built or bug is fixed without disrupting the original project. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Fork&lt;/code&gt; button can be found at the top of a repository’s Github page.&lt;/p&gt;

&lt;p&gt;After the &lt;code class=&quot;highlighter-rouge&quot;&gt;Fork&lt;/code&gt; has been made, the next step is to clone the &lt;strong&gt;forked&lt;/strong&gt; copy locally:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;git clone git@github.com:&amp;lt;your_username&amp;gt;/fetching-gem.git
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Cloning the repository locally will automatically add the &lt;code class=&quot;highlighter-rouge&quot;&gt;origin&lt;/code&gt; git remote URL to the code directory. Additionally, adding the source remote URL right away is a great way to make sure that local code and the master remote code can easily stay in sync.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;fetching-gem/
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;git remote add upstream git@github.com:covermymeds/fetching-gem.git
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;git remote -v

origin git@github.com:yez/fetching-gem.git &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
origin  git@github.com:yez/fetching-gem.git &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
upstream  git@github.com:covermymeds/fetching-gem.git &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
upstream  git@github.com:covermymeds/fetching-gem.git &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The above command adds a new remote, &lt;code class=&quot;highlighter-rouge&quot;&gt;upstream&lt;/code&gt;, to the directory. With this remote in place, a &lt;code class=&quot;highlighter-rouge&quot;&gt;git fetch upstream&lt;/code&gt; command will grab the latest updates from the original repository.&lt;/p&gt;

&lt;p&gt;Exploring unfamiliar code is not the most intuitive process, but thankfully a number of &lt;a href=&quot;https://jakeyesbeck.com/2015/10/25/how-to-traverse-foreign-ruby-code/&quot;&gt;blog posts&lt;/a&gt; have been written about the topic.&lt;/p&gt;

&lt;h2 id=&quot;reproduce-the-issue&quot;&gt;4. Reproduce the issue&lt;/h2&gt;

&lt;p&gt;With the fork cloned locally and remote pointers all set up, it is time to reproduce and address the issue. Since this particular issue was a feature enhancement ask, “reproducing” the issue consisted of calling a method with the wrong arguments and expecting it to fail:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;fetching-gem&#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetching_array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Fetching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetching_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;ArgumentError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrong&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arguments&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Success! The code definitely does not support the &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable#first(n)&lt;/code&gt; behaviour, so there is indeed work to be done.&lt;/p&gt;

&lt;h2 id=&quot;fix-the-issue&quot;&gt;5. Fix the issue&lt;/h2&gt;

&lt;p&gt;Both when adding code and altering existing code, it is important to make sure it is tested. In most cases, the project under revision will have chosen a particular testing library and have some amount of tests. Adding the appropriate tests at the same time as the patched code will boost the library’s maintainer(s) confidence in the patch.&lt;/p&gt;

&lt;p&gt;Adhering to the style of the code under manipulation is also important. From test example descriptions to variable declaration styling, consistency is a complexity reducing concept that is extremely valuable later on.&lt;/p&gt;

&lt;p&gt;For brevity’s sake, the finer details surrounding my example &lt;code class=&quot;highlighter-rouge&quot;&gt;fetching-gem&lt;/code&gt; patch can be found &lt;a href=&quot;https://github.com/covermymeds/fetching-gem/commit/749624e89100066e514b0521ea69f2e91a226309&quot;&gt;on Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;submit-a-pr&quot;&gt;6. Submit a PR&lt;/h2&gt;

&lt;p&gt;With the contribution guidelines adhered to, the code altered, and the issue taken care of, it is time to submit the long anticipated patch.&lt;/p&gt;

&lt;p&gt;A well crafted pull request (PR) message consists of a few key elements:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It is concise. Too much explination will be glossed over and ends up doing more harm than good.&lt;/li&gt;
  &lt;li&gt;A special “Resolved #&lt;issue number=&quot;&quot;&gt;&quot; text exists, allowing Github to automatically reference and resolve the issue upon a successul merge.&lt;/issue&gt;&lt;/li&gt;
  &lt;li&gt;If applicable, an example of the new behaviour is given.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The pull request that I recently added to &lt;code class=&quot;highlighter-rouge&quot;&gt;fetching-gem&lt;/code&gt; looked like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/submit_pr.png&quot; alt=&quot;Submit a PR&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Another possible check when submitting a PR involves continuous integrations. If a project automatically builds its test suite with a service like &lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis&lt;/a&gt;, Github will supply some checks at the bottom of the PR:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/make_sure_ci_passes.png&quot; alt=&quot;Check CI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If, for some reason, this status is not green and the tests did not pass, use the &lt;code class=&quot;highlighter-rouge&quot;&gt;Details&lt;/code&gt; link to find out more information why.&lt;/p&gt;

&lt;h2 id=&quot;feel-awesome&quot;&gt;7. Feel Awesome!&lt;/h2&gt;

&lt;p&gt;Pending continuous integration passing and the repository’s maintainer(s) signing off on the change, a patch will be accepted into the project. What a fantastic feeling that is! Awesome maintainers (like the &lt;code class=&quot;highlighter-rouge&quot;&gt;fetching-gem&lt;/code&gt; maintainer &lt;code class=&quot;highlighter-rouge&quot;&gt;mikegee&lt;/code&gt;) will show their appreciation directly on the PR, immortalizing your contribution for all days to come.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/feel_great.png&quot; alt=&quot;Feel Great&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;b-repeat-4---6&quot;&gt;7b. Repeat 4 - 6&lt;/h2&gt;

&lt;p&gt;In the case that the submitted code is not &lt;em&gt;exactly&lt;/em&gt; what the maintainer(s) is looking for, some additional work might be warranted. This back and forth could be thought of as frustrating, but it is also a great learning opportunity. When else is feedback so easily received about one’s code from people they would have probably never met otherwise?&lt;/p&gt;

&lt;p&gt;Open source projects have tremendous value and a strong presence in the technology ecosystem. Contributing to these projects is an easy way to show appreciation and feel like a valued member of the open source community.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How To Parallelize Ruby HTTP Requests</title>
   <link href="https://jakeyesbeck.com/2016/01/10/how-to-parallelize-ruby-http-requests/"/>
   <updated>2016-01-10T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/01/10/how-to-parallelize-ruby-http-requests</id>
   <content type="html">&lt;p&gt;It turns out that managing web requests is quite important when doing web development. A web application backed by an external or internal API can issue &lt;strong&gt;a lot&lt;/strong&gt; of requests when rendering a seemingly simple web page. How those requests are made and in what order is very important. With improper parallelization, an end user’s entire experience can go from delightful to horrific in a matter of seconds.&lt;/p&gt;

&lt;h2 id=&quot;the-build-up&quot;&gt;The Build Up&lt;/h2&gt;

&lt;p&gt;A basic Ruby on Rails application might have the following features:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; can create a favorite of an item, creating a &lt;code class=&quot;highlighter-rouge&quot;&gt;FavoriteItem&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; can add an item to their wishlist, creating a &lt;code class=&quot;highlighter-rouge&quot;&gt;WishlistItem&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; can buy an item, creating a &lt;code class=&quot;highlighter-rouge&quot;&gt;TransactionItem&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each model this system uses is backed by an API. &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;TransactionItem&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;WishlistItem&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;FavoriteItem&lt;/code&gt; models all require a remote HTTP request for their information.&lt;/p&gt;

&lt;p&gt;As a web application experiences growth, this structure is not uncommon. The same API might back a mobile app, website, and any other internal tooling to help this company with its day to day affairs.&lt;/p&gt;

&lt;p&gt;The API that this application uses works in a two phase manner:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A user can be requested by their &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt;.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/users/:id&lt;/code&gt; returns a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; corresponding to the given &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Each supporting model is requested with the same &lt;code class=&quot;highlighter-rouge&quot;&gt;user_id&lt;/code&gt;.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/users/:id/favorite_items&lt;/code&gt; will return an array of &lt;code class=&quot;highlighter-rouge&quot;&gt;FavoriteItems&lt;/code&gt; for the specified &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The contract of this API is for all intents an purposes, non-negotiable. In-lined data or other request saving patterns are not available, the client must use the API as provided.&lt;/p&gt;

&lt;h2 id=&quot;sequential-approach&quot;&gt;Sequential Approach&lt;/h2&gt;

&lt;p&gt;Within this example application, the most request intensive page is the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&#39;s&lt;/code&gt; history page. The history page consists of everything the user has done. &lt;code class=&quot;highlighter-rouge&quot;&gt;Items&lt;/code&gt; a user has added to their favorites resulting in &lt;code class=&quot;highlighter-rouge&quot;&gt;FavoriteItems&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Items&lt;/code&gt; bought by the user resulting in &lt;code class=&quot;highlighter-rouge&quot;&gt;TransactionItems&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;Items&lt;/code&gt; added to a user’s wish list resulting in &lt;code class=&quot;highlighter-rouge&quot;&gt;WishListItems&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To complement the (ex/in)ternal API, two helper methods exist on each model: &lt;code class=&quot;highlighter-rouge&quot;&gt;remote_find&lt;/code&gt; which accepts an &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; or array of &lt;code class=&quot;highlighter-rouge&quot;&gt;ids&lt;/code&gt;, returning the matching models, and &lt;code class=&quot;highlighter-rouge&quot;&gt;remote_find_by_user_id&lt;/code&gt; which accepts a &lt;code class=&quot;highlighter-rouge&quot;&gt;user_id&lt;/code&gt; and returns an array of &lt;code class=&quot;highlighter-rouge&quot;&gt;ids&lt;/code&gt; for the corresponding model.&lt;/p&gt;

&lt;p&gt;Leveraging the API and these two helper methods, a serial version of a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&#39;s&lt;/code&gt; pertinent data could look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserHistoryController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remote_find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

    &lt;span class=&quot;vi&quot;&gt;@favorite_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;FavoriteItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remote_find_by_user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;vi&quot;&gt;@wish_list_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;WishlistItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remote_find_by_user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;vi&quot;&gt;@transaction_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;TransactionItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remote_find_by_user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However slow it may be, this code will indeed fulfill its duty. First the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; is found, then all the supporting information about a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&#39;s&lt;/code&gt; history is retrieved one by one from the API.&lt;/p&gt;

&lt;p&gt;In a worst case scenario, assume the API returns an individual request in about &lt;code class=&quot;highlighter-rouge&quot;&gt;150ms&lt;/code&gt;. With &lt;code class=&quot;highlighter-rouge&quot;&gt;4&lt;/code&gt; requests, this means that &lt;strong&gt;only required page elements will take &lt;code class=&quot;highlighter-rouge&quot;&gt;600ms&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tacking on view rendering, whatever data processing or formatting that needs to be done at the presentation layer, and finally some amount of Javascript, this page becomes objectively &lt;em&gt;slow&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;enter-em-synchrony&quot;&gt;Enter &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;As with most problems, someone smart has had it before and probably done something about it. Luckily, this particular problem has been addressed by &lt;a href=&quot;https://github.com/igrigorik/em-synchrony&quot;&gt;Ilya Grigorik’s EM-Synchrony library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Grigorik’s library leverages the use of Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Fibers&lt;/code&gt; to parallelize* code execution.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*Note: Because of the Global Interpreter Lock (GIL) present in MRI, true parallelization is not possible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The real benefit of using &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; is the way it handles scheduling the underlying &lt;code class=&quot;highlighter-rouge&quot;&gt;Fibers&lt;/code&gt;. A Ruby &lt;code class=&quot;highlighter-rouge&quot;&gt;Fiber&lt;/code&gt; is basically a &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread&lt;/code&gt; that is not automatically scheduled by the Ruby VM. This means that it is up to the programmer to let the &lt;code class=&quot;highlighter-rouge&quot;&gt;Fiber&lt;/code&gt; know when it should relinquish control to another &lt;code class=&quot;highlighter-rouge&quot;&gt;Fiber&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since this example is almost completely bound by &lt;code class=&quot;highlighter-rouge&quot;&gt;Input/Output&lt;/code&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;I/O&lt;/code&gt;) operations, it is a perfect candidate for &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To use &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; effectively, existing requests must be broken up into pieces that can accessed independently. A &lt;code class=&quot;highlighter-rouge&quot;&gt;requests&lt;/code&gt; method can be created to extract details surrounding each request. The result of the &lt;code class=&quot;highlighter-rouge&quot;&gt;requests&lt;/code&gt; method must be an enumerable.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: As explained &lt;a href=&quot;#caveats&quot;&gt;below&lt;/a&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; can only be used with supported HTTP clients.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserHistoryController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;requests&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;method: :remote_find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;arg: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;instance_var: :@user&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;FavoriteItem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;method: :remote_find_by_user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;arg: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;instance_var: :@favorite_items&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;WishListItem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;method: :remote_find_by_user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;arg: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;instance_var: :@wish_list_items&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;TransactionItem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;method: :remote_find_by_user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;arg: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;instance_var: :@transaction_items&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;For the sake of being explicit, this very redundant helper method will be used to iterate over requests and allow &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; to process them in parallel:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserHistoryController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;CONCURRENCY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;EM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;synchrony&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;EM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Synchrony&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FiberIterator&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONCURRENCY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Example of below with real values:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# key = Transaction&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Transation.remote_find_by_user_id(@user.id)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;instance_variable_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:instance_var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;no&quot;&gt;EM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stop&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A few important lines of this solution are worth a closer look:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;CONCURRENCY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This line tells &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; how many &lt;code class=&quot;highlighter-rouge&quot;&gt;Fibers&lt;/code&gt; it is allowed to run at once. Since the example needed to request four remote  resources, the concurrency amount is set to four.&lt;/p&gt;

&lt;p&gt;The next line of interest is:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;EM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Synchrony&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FiberIterator&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONCURRENCY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here is where the actual work is done. After meticulously crafting the structure of the &lt;code class=&quot;highlighter-rouge&quot;&gt;requests&lt;/code&gt; hash, the &lt;code class=&quot;highlighter-rouge&quot;&gt;FiberIterator&lt;/code&gt; will pick the next element from the list and give it to a &lt;code class=&quot;highlighter-rouge&quot;&gt;Fiber&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally the line stopping of Event Machine can not go unnoticed.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;EM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This method has literally no documentation but is in every example of using Event Machine, so it is probably very crucial.&lt;/p&gt;

&lt;p&gt;And that is all there is to it! All four HTTP requests can now be run in parallel, resulting in a major speed up and a much happier user experience.&lt;/p&gt;

&lt;h2 id=&quot;caveats&quot;&gt;Caveats&lt;/h2&gt;

&lt;p&gt;A few considerations must be made in order to use &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; effectively.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;A compliant HTTP library must be used.&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/igrigorik/em-http-request#extensions&quot;&gt;As em-http-client’s the README&lt;/a&gt; a compliant HTTP library must be used when making the requests. &lt;a href=&quot;https://github.com/lostisland/faraday&quot;&gt;Faraday&lt;/a&gt; is my favorite compliant library and it has worked great for me so far. Unfortunately, the very popular &lt;code class=&quot;highlighter-rouge&quot;&gt;HTTParty&lt;/code&gt; library is not compliant and therefore no one may “Party Hard” when using &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;HTTParty&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;One size does not fit all.&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Unlike the described example, not all code can be saved by &lt;code class=&quot;highlighter-rouge&quot;&gt;EM-Synchrony&lt;/code&gt;. If a request depends on the result of another request, sharing those results between &lt;code class=&quot;highlighter-rouge&quot;&gt;Fibers&lt;/code&gt; is neither simple, nor a good idea.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Passages Rails Engine</title>
   <link href="https://jakeyesbeck.com/2016/01/03/passages/"/>
   <updated>2016-01-03T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2016/01/03/passages</id>
   <content type="html">&lt;p&gt;Routing in the Ruby on Rails world can, at times, be a tad confusing. The &lt;a href=&quot;https://guides.rubyonrails.org/routing.html&quot;&gt;official Rails guide&lt;/a&gt; is very helpful for the basics; but, as an application grows, it can become hard to remember specific details about every single route.&lt;/p&gt;

&lt;h2 id=&quot;existing-routing-tools&quot;&gt;Existing Routing Tools&lt;/h2&gt;

&lt;p&gt;To remedy the issue of route complexity, a few helpful tools already exist. The most useful one is &lt;code class=&quot;highlighter-rouge&quot;&gt;rake routes&lt;/code&gt;, which can be executed in the working directory of a Rails application. This tool requires that the application be on the developer’s local system, which is fine for applications that a developer owns, but what about services that the developer does not own?&lt;/p&gt;

&lt;p&gt;While this problem might not exist for everyone, chances are at least one poor software engineer has been slapped in the face with a &lt;code class=&quot;highlighter-rouge&quot;&gt;404&lt;/code&gt; page and shouted: &lt;em&gt;“I know that route exists! Why doesn’t this work?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Another helpful tool in development mode is this screen:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/no_route_page.png&quot; alt=&quot;Default Rails Dev No Route&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This page provides the ability to enter search terms that match words in the &lt;code class=&quot;highlighter-rouge&quot;&gt;paths&lt;/code&gt; of specfic routes. However, similarly to &lt;code class=&quot;highlighter-rouge&quot;&gt;rake routes&lt;/code&gt;, this screen is only accessible in development mode. While this tool is still extremely useful, there could be cases when route inspection would be helpful without running the server locally.&lt;/p&gt;

&lt;h2 id=&quot;new-hotness&quot;&gt;New Hotness&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/yez/passages&quot;&gt;The Passages Rails Engine&lt;/a&gt; was created to fulfill two main purposes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; To expose routes of a Ruby on Rails application either during or outside development mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Enable searching on multiple pieces of a route’s information (HTTP verb, controller, path, etc).&lt;/p&gt;

&lt;p&gt;Some might wonder by &lt;strong&gt;1&lt;/strong&gt; would even be valuable. Imagine for a moment that a team of engineers decides that they need an internal API to power their various applications. Perhaps while developing this API, some basic documentation is written but never actually kept up to date. Maybe the API changes so fast that documentation just falls behind.&lt;/p&gt;

&lt;p&gt;Whatever the reason, it becomes laborious for the consumers of that internal API to constantly ask which route does what and which parameters are expected in each URL.&lt;/p&gt;

&lt;p&gt;Internal APIs are not the only candidate for &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt;. An external API can also benefit from discoverable routing in lieu of or in addition to documentation. Since &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; has the option to use HTTP Basic Authentication, securing &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; is as simple as setting two &lt;code class=&quot;highlighter-rouge&quot;&gt;ENV&lt;/code&gt; variables.&lt;/p&gt;

&lt;p&gt;Purpose &lt;strong&gt;2&lt;/strong&gt; is an attempt to reduce a large application’s route pile by expanding each route’s search surface area. A user of &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; might want to know of all the &lt;code class=&quot;highlighter-rouge&quot;&gt;PUT&lt;/code&gt; routes or routes that map to a &lt;code class=&quot;highlighter-rouge&quot;&gt;destroy&lt;/code&gt; action. Like its predecessor, &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&#39;&lt;/code&gt; route path search is also extremely valuable.&lt;/p&gt;

&lt;p&gt;With (hopefully) the help of the open source community, the types of useful search features for &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; will expand from these very humble beginnings.&lt;/p&gt;

&lt;h2 id=&quot;demo&quot;&gt;Demo&lt;/h2&gt;

&lt;p&gt;After following the &lt;a href=&quot;https://github.com/yez/passages#install&quot;&gt;installation guide from the project’s README&lt;/a&gt;, A very basic use of &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; would look like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/passages_demo.gif&quot; alt=&quot;Passages Demo&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;contributing&quot;&gt;Contributing&lt;/h2&gt;

&lt;p&gt;Like most Open Source projects, &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; has many areas that welcome modification. Specifically, the design and search functionalities are suitable candidates for enhancement.&lt;/p&gt;

&lt;p&gt;Please feel free to &lt;a href=&quot;https://github.com/yez/passages&quot;&gt;fork the repository&lt;/a&gt; or create an issue on Github if something seems wrong or out of place.&lt;/p&gt;

&lt;p&gt;Currently, &lt;code class=&quot;highlighter-rouge&quot;&gt;Passages&lt;/code&gt; only supports Ruby on Rails 4. It will most likely be upgraded when Ruby on Rails 5 is released but there are no plans to support Ruby on Rails 3 or older.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Things I Wish I Knew When I Started Programming</title>
   <link href="https://jakeyesbeck.com/2015/12/27/what-i-would-tell-myself-when-i-started-programming/"/>
   <updated>2015-12-27T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/12/27/what-i-would-tell-myself-when-i-started-programming</id>
   <content type="html">&lt;p&gt;If by some magical event I could go back in time to the day before I started my first job as a software engineer, this is what I would say.&lt;/p&gt;

&lt;h2 id=&quot;drive-slow&quot;&gt;Drive Slow&lt;/h2&gt;

&lt;p&gt;I mentioned a similar message in &lt;a href=&quot;https://jakeyesbeck.com/2015/09/06/stop-and-take-a-moment/&quot;&gt;a previous post&lt;/a&gt; and I believe it is worth repeating. When starting a new job or a new career, it is easy to place external pressures on ourselves regarding time. This is a common issue that can arise when comparing one’s own work with those around them. As the new employee, noticing and measuring your own speed and efficiency against existing personnel can feel like the correct thing to do; however, chasing the “competition” or “proving that you are just as fast as them” will only result in high stress levels and bug riddled software.&lt;/p&gt;

&lt;p&gt;The people who seem “fast” or come off as a “10x engineer” were not born that way. They took their time and learned their craft. And with that, they have slowly accelerated their process and patterns to make them appear extremely quick and efficient.&lt;/p&gt;

&lt;p&gt;Deadlines should be thought of as real and valid; however, working at lightning speed to try and meet those deadlines will end up causing more work in the long run. What would be better, missing a deadline by a day or making a deadline and incurring so many bugs and tech debt that it takes two weeks to clean everything up?&lt;/p&gt;

&lt;h2 id=&quot;abl&quot;&gt;ABL&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Glengarry Glen Ross’s&lt;/em&gt; iconic scene has very clear message: &lt;strong&gt;A&lt;/strong&gt;lways &lt;strong&gt;B&lt;/strong&gt;e &lt;strong&gt;C&lt;/strong&gt;losing, meaning that one should constantly strive to be in the process completing a sale. When starting out writing software and even after years of doing it, a similar attitude can be extremely helpful: &lt;strong&gt;A&lt;/strong&gt;lways &lt;strong&gt;B&lt;/strong&gt;e &lt;strong&gt;L&lt;/strong&gt;earning.&lt;/p&gt;

&lt;p&gt;From day one to day one thousand, learning and absorbing new information is very important. A key to learning new things is in asking questions. When starting a new job or a new career, there seems to be a stigma attached to asking questions. We are all under the impression that &lt;em&gt;“they hired me to do this job, they must assume I know exactly what I’m doing.”&lt;/em&gt; This mentality can inhibit our natural inquisitive nature which is a great catalyst to learning.&lt;/p&gt;

&lt;p&gt;Ridicule and impostor syndrome are the most likely the reasons stopping people from asking questions. The idea that questions might expose a person as not “good enough” or “smart enough” for their job is ridiculous and often unfounded. Getting over these fears early in one’s career is extremely important. Questions should be encouraged and celebrated. Ask questions every single day, ask a lot of them but make sure not to ask the same one too many times. No one enjoys repeating themselves.&lt;/p&gt;

&lt;h2 id=&quot;it-is-ok-to-be-wrong&quot;&gt;It is Ok to be Wrong&lt;/h2&gt;

&lt;p&gt;Similar to not asking questions, most new engineers are terrified of being wrong. A golden rule is to be correct frequently, but no one is capable of being correct all the time. The trick to being wrong is how a person reacts when it happens. There is a huge difference between promoting a technique or solution and being closed-minded to alternatives.&lt;/p&gt;

&lt;p&gt;If someone was never wrong, how could they learn? And if they did not learn, how could they &lt;strong&gt;A&lt;/strong&gt;lways &lt;strong&gt;B&lt;/strong&gt;e &lt;strong&gt;L&lt;/strong&gt;earning? Tackling instances of being wrong with an open mind helps refine a person’s skills, shaping them with feedback from others. While this mentality, like others already mentioned, is relevant throughout a person’s career, it is especially important in the beginning. In the beginning a person is likely wrong a lot of the time. This means that in the beginning a person has the most opportunity to grow; to be wrong and learn from those mistakes. Internalizing these mistakes can help bolster a person’s technical skills and confidence.&lt;/p&gt;

&lt;h2 id=&quot;rtfs&quot;&gt;R.T.F.S.&lt;/h2&gt;

&lt;p&gt;At the onset of one’s career, it is easy to treat third party software or services as magical boxes of mystery. However, this is not necessary. It is actually &lt;a href=&quot;https://jakeyesbeck.com/2015/10/25/how-to-traverse-foreign-ruby-code/&quot;&gt;very easy to open and read the source&lt;/a&gt; of many third party applications (especially in web development). Therefore, it becomes imperative to &lt;strong&gt;R&lt;/strong&gt;ead &lt;strong&gt;T&lt;/strong&gt;he &lt;strong&gt;F&lt;/strong&gt;reaking &lt;strong&gt;S&lt;/strong&gt;ource.&lt;/p&gt;

&lt;p&gt;Reading and having at least a basic understanding of how a piece of third party software works is paramount for a new developer. If foreign code is treated as magic, that is all it will ever be. This magic can become a crutch that an innocent new developer may find themselves leaning against more and more until it eventually breaks, leaving the developer confused and helpless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: Not all third party software’s source can be read as not all of it is open source. If this is the case, do not try to read the source, it will not make much sense.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Who wants to be confused and helpless? No one wants that and no one needs to experience that. Reading the source code of a library or crucial bit of third party open source software can help bring light to an otherwise shrouded system, bringing a new level of depth to a developer’s understanding.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introduction to Rails 5 Attributes</title>
   <link href="https://jakeyesbeck.com/2015/12/20/rails-5-attributes/"/>
   <updated>2015-12-20T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/12/20/rails-5-attributes</id>
   <content type="html">&lt;p&gt;Shortly after the tenth anniversary of Ruby on Rails 1.0, Rails 5.0 Beta has been announced. While the main character of this release was without a doubt &lt;code class=&quot;highlighter-rouge&quot;&gt;ActionCable&lt;/code&gt;, other really great features have made their debut.&lt;/p&gt;

&lt;h2 id=&quot;types-of-changes&quot;&gt;Types of Changes&lt;/h2&gt;

&lt;p&gt;One feature that particularly stood out is the introduction of &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord Attributes&lt;/code&gt;. This feature allows a developer to assert a specific type for a given attribute and an optional default value. It is not strict type validation (&lt;a href=&quot;https://jakeyesbeck.com/2015/11/29/updated-validates-type/&quot;&gt;which I have a very strong affinity for&lt;/a&gt;), but it does define explicit type coercion that can be very useful.&lt;/p&gt;

&lt;p&gt;Given an example application that deals with &lt;code class=&quot;highlighter-rouge&quot;&gt;Transactions&lt;/code&gt;, a single table and model might exist:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateTransactions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:transactions&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:item_name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:quantity&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:success&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decimal&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:price&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This structure, like most in the wild, could have been created before all edge cases were thought through. For some reason, &lt;code class=&quot;highlighter-rouge&quot;&gt;success&lt;/code&gt; is a &lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt; instead of a &lt;code class=&quot;highlighter-rouge&quot;&gt;Boolean&lt;/code&gt;. While this problem might seem trivial, imagine a system where hundreds of millions of &lt;code class=&quot;highlighter-rouge&quot;&gt;transactions&lt;/code&gt; exist.&lt;/p&gt;

&lt;p&gt;In such a system the entire column might not be able to change without incurring downtime. This is a perfect example problem that &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt; can help remedy.&lt;/p&gt;

&lt;p&gt;Starting simple, a single line can be added to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Transaction&lt;/code&gt; class definition to coerce &lt;code class=&quot;highlighter-rouge&quot;&gt;success&lt;/code&gt; to a &lt;code class=&quot;highlighter-rouge&quot;&gt;boolean&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:boolean&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Using the same logic that &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; uses for database column coercion, we can see attributes in action!&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;success: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;yes&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;success&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;success: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;f&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;success&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;success: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;success&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Just like that, the schema has been improved. Aside from raw &lt;code class=&quot;highlighter-rouge&quot;&gt;SQL&lt;/code&gt; update statements, this code now prevents strings like &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;maybe&quot;&lt;/code&gt; from littering the &lt;code class=&quot;highlighter-rouge&quot;&gt;success&lt;/code&gt; column of the &lt;code class=&quot;highlighter-rouge&quot;&gt;transactions&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;Before &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt;, a callback or custom setter method would have been the preferred way to address this problem. However, with this new built in solution for mismatched database column types, old one-off or ad-hoc solutions can be replaced with this new standard.&lt;/p&gt;

&lt;h2 id=&quot;the-friendly-type&quot;&gt;The Friendly Type&lt;/h2&gt;

&lt;p&gt;With such a clean DSL, it is obvious that a lot of time and thought went into the design of &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt;. Being able to specify how a model should interact with the persistence layer is a powerful tool.&lt;/p&gt;

&lt;p&gt;The full list of supported types that &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt; provides can be found deep in the source code for &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; or right here:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#Supported Types&lt;/span&gt;

&lt;span class=&quot;ss&quot;&gt;:big_integer&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:binary&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:boolean&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:date&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:date_time&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:decimal&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:float&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:integer&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;:time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Each of these types has their own place and value in a system. Their purpose is simple: to make the experience between developer and framework fluid.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Attribute&lt;/code&gt; feature is not restricted to database columns. If an attribute is only used during the life cycle of an object, it too can benefit from type coercion.&lt;/p&gt;

&lt;p&gt;For instance, if a &lt;code class=&quot;highlighter-rouge&quot;&gt;confirmed_at&lt;/code&gt; attribute had a useful purpose for a &lt;code class=&quot;highlighter-rouge&quot;&gt;Transaction&lt;/code&gt;, but the format of it could vary, the &lt;code class=&quot;highlighter-rouge&quot;&gt;Attribute&lt;/code&gt; module can step in and keep things clean.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Transaction&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:confirmed_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:date_time&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Without adding a new column or defining an &lt;code class=&quot;highlighter-rouge&quot;&gt;attr_accessor&lt;/code&gt; for the &lt;code class=&quot;highlighter-rouge&quot;&gt;confirmed_at&lt;/code&gt; attribute, the &lt;code class=&quot;highlighter-rouge&quot;&gt;:date_time&lt;/code&gt; coercion works perfectly:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;confirmed_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2015-12-12 03:00&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;confirmed_at&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Sat, 12 Dec 2015 03:00:00 UTC +00:00&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;confirmed_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;2015/12/12&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;confirmed_at&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Sat, 12 Dec 2015 00:00:00 UTC +00:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Since most Ruby on Rails applications deal with strings via form encoded data, it is easy to see just how valuable the &lt;code class=&quot;highlighter-rouge&quot;&gt;Attribute&lt;/code&gt; module can be.&lt;/p&gt;

&lt;h2 id=&quot;out-of-the-box-typing&quot;&gt;Out of the Box Typing&lt;/h2&gt;

&lt;p&gt;A fantastic detail about &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt; is that type coercion is not limited to only “supported” types. Any object that adheres to a proper contract may be used.&lt;/p&gt;

&lt;p&gt;To help illustrate this feature, we can assume that all prices in the database have been changed to only deal with cents. This helps remove some complexities with floating point math oddities and prevents nefarious &lt;strong&gt;Office Space/Superman III&lt;/strong&gt; bugs from creeping up.&lt;/p&gt;

&lt;p&gt;Given a &lt;code class=&quot;highlighter-rouge&quot;&gt;MoneyType&lt;/code&gt; object:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MoneyType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Integer&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;type_cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;$&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;price_in_dollars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;price_in_dollars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;An important takeaway here is the inheritance and &lt;code class=&quot;highlighter-rouge&quot;&gt;type_cast&lt;/code&gt; method definition. Both elements are necessary to create a custom type that the &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt; module can use effectively.&lt;/p&gt;

&lt;p&gt;To use this new type, an initialized object is passed to the &lt;code class=&quot;highlighter-rouge&quot;&gt;attribute&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MoneyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then, if all keystrokes were done with style and grace, the effects should look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;price: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;$10.00&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT * FROM transactions WHERE price = 1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The observed behaviour here is very interesting. A string representing a money amount can be coerced to an &lt;code class=&quot;highlighter-rouge&quot;&gt;Integer&lt;/code&gt; value representing the same data. Instead of the &lt;code class=&quot;highlighter-rouge&quot;&gt;MoneyType&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;type_cast&lt;/code&gt; method being extracted and used many times in controller or other model methods, it can be centralized to one specific spot.&lt;/p&gt;

&lt;p&gt;Like the previous example, this solution is not the only way to achieve the desired result; however, it is unique enough to inspire new ways of thinking about these problems.&lt;/p&gt;

&lt;h2 id=&quot;type-validation&quot;&gt;Type Validation&lt;/h2&gt;

&lt;p&gt;Avoiding hidden type coercion was a driving force when I created the &lt;a href=&quot;https://github.com/yez/validates_type&quot;&gt;validates_type&lt;/a&gt; gem. With &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt;, that coercion is still there but can be explicitly specified in a model’s definition. While this is a great step forward, I still find value in rejecting data of the wrong type. As a previous example can illustrate: why does the string &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;yes&quot;&lt;/code&gt; map to the boolean value &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;? It does make some sense but &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;yes&quot;&lt;/code&gt; is not a boolean.&lt;/p&gt;

&lt;p&gt;The addition of &lt;code class=&quot;highlighter-rouge&quot;&gt;Attributes&lt;/code&gt; will hopefully promote some new patterns and considerations around dealing with types in Ruby on Rails applications. Data consistency and reliability are important, it is exciting to see people making steps toward it in the Rails community.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Refinements</title>
   <link href="https://jakeyesbeck.com/2015/12/13/ruby-refinements/"/>
   <updated>2015-12-13T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/12/13/ruby-refinements</id>
   <content type="html">&lt;p&gt;The Ruby language provides many powerful tools for software engineers to utilize. For instance, classes that have been previously defined and evaluated can be reopened and changed. This is commonly referred to as &lt;em&gt;“monkey patching”&lt;/em&gt;, a term which elicits almost universal disdain among Ruby developers.&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;A reason that monkey patched code has issues lies in the scope of the changed code. If previously defined code is changed at an arbitrary time, all other parts of the application suffer from those changes.&lt;/p&gt;

&lt;p&gt;Why would someone need to change an existing class? Perhaps an included &lt;code class=&quot;highlighter-rouge&quot;&gt;gem&lt;/code&gt; needs to be altered in a small way to behave correctly in a very specific system. Or maybe, there exists a very dark area of a codebase that must not be touched directly for fear that the entire application will go under.&lt;/p&gt;

&lt;p&gt;Whatever the case, patching code that has been already defined happens, and it usually happens poorly.&lt;/p&gt;

&lt;p&gt;These problems can be especially nefarious if the patches are not in automatically loaded files. For example, say we have a &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dog.rb&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:trained&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;woof woof&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then in file loaded later, the &lt;code class=&quot;highlighter-rouge&quot;&gt;bark&lt;/code&gt; method changes to be much more formal:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;training.rb&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Training&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;trained&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;Woof woof, good sir.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After the &lt;code class=&quot;highlighter-rouge&quot;&gt;Traning&lt;/code&gt; class is loaded, any consumers of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class will be in for a surprise whenever the &lt;code class=&quot;highlighter-rouge&quot;&gt;bark&lt;/code&gt; method is called. Even worse, when a confused developer opens the &lt;code class=&quot;highlighter-rouge&quot;&gt;dog.rb&lt;/code&gt; class to check &lt;code class=&quot;highlighter-rouge&quot;&gt;bark&lt;/code&gt;’s functionality, they will not see the patched version.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; woof woof&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;./training&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;training&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Training&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;training&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Woof woof, good sir.&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Woof woof, good sir.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As shown, the second initialized &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; barks the same way as the trained &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt;. Globally, the way a &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; barks has been changed after the &lt;code class=&quot;highlighter-rouge&quot;&gt;training&lt;/code&gt; file has been included.&lt;/p&gt;

&lt;h2 id=&quot;enter-refinements&quot;&gt;Enter Refinements&lt;/h2&gt;

&lt;p&gt;An alternative way to extend a class’ functionality is by using the built in ruby construct: &lt;code class=&quot;highlighter-rouge&quot;&gt;Refinements&lt;/code&gt;. Refinements are context specific alterations to a class’ methods.&lt;/p&gt;

&lt;p&gt;To refine the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class, a &lt;code class=&quot;highlighter-rouge&quot;&gt;module&lt;/code&gt; needs to be written:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;SophisticatedDog&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;refine&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;Woof woof, good sir.&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The interesting piece here is the &lt;code class=&quot;highlighter-rouge&quot;&gt;refine&lt;/code&gt; method. This method returns an overlaid module specific to the class passed into it, allowing a very small scoped change of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;To include this Refinement in the place where it is needed, the &lt;code class=&quot;highlighter-rouge&quot;&gt;using&lt;/code&gt; method can be added to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Training&lt;/code&gt; class.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Training&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SophisticatedDog&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;trained&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, the changes to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; method are contained within the &lt;code class=&quot;highlighter-rouge&quot;&gt;Training&lt;/code&gt; class:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; woof woof&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;./training&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;training&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Training&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;training&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Woof woof, good sir.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Neither the passed in dog, nor newly created dogs’ bark method has been permanently changed:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; woof woof&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; woof woof&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;No more surprise behaviour! Each new &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; is created just as unrefined and unsophisticated as ever.&lt;/p&gt;

&lt;h2 id=&quot;super-cool&quot;&gt;Super Cool&lt;/h2&gt;

&lt;p&gt;Another problem with traditional monkey patching is that the patched method is no longer accessible.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;woof woof&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Then later:&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;, good sir.&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; NoMethodError: super: no superclass method `bark&#39; for Dog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The original implementation of &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; had a very specific string that might not want to be duplicated. When the class is monkey patched, the original method is replaced and &lt;code class=&quot;highlighter-rouge&quot;&gt;super&lt;/code&gt; is not accessible.&lt;/p&gt;

&lt;p&gt;In a less silly example, maybe the method being patched had some valuable code a patch could have used. Since Refinements are not strict code overwrites, they maintain the &lt;code class=&quot;highlighter-rouge&quot;&gt;super&lt;/code&gt; functionality found in inheritance:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;woof woof&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;SubWoofer&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;refine&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DogTest&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SubWoofer&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;DogTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;woof&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bark&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;woof woof&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;SubWoofer&lt;/code&gt; Refinement was able to call the existing &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog#bark&lt;/code&gt; method and change it how it saw fit. This keeps the code around barking DRY. Since Refinements are intended to extend or refine existing code, it makes sense that they could use the existing code to their benefit. When that existing code is changed, it would be arduous to make every single Refinement aware.&lt;/p&gt;

&lt;p&gt;Using Refinements is a nice alternative to the sledgehammer that is monkey patching. Bending a class to fit a very specific need in an encapsulated manner can mean the difference between a stable system and one riddled with hard to track down bugs. While Refinements still have their own drawbacks, they are much less intrusive than the alternative.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to use Rails Strong Parameters</title>
   <link href="https://jakeyesbeck.com/2015/12/06/how-to-use-rails-strong-parameters/"/>
   <updated>2015-12-06T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/12/06/how-to-use-rails-strong-parameters</id>
   <content type="html">&lt;p&gt;In the latest major version of Ruby on Rails, &lt;strong&gt;Strong Parameters&lt;/strong&gt; were introduced. The intent of this addition was to enable consistent and reliable parameter checking. Using Strong Parameters is simple and intuitive. It provides a very clean method API to help keep controllers DRY.&lt;/p&gt;

&lt;p&gt;However, knowing when to use Strong Parameters and how to use them correctly is very important. After all, what good is parameter validation if it is in the wrong place or conveys the wrong message?&lt;/p&gt;

&lt;h2 id=&quot;hit-the-books&quot;&gt;Hit the Books&lt;/h2&gt;

&lt;p&gt;The trusty &lt;em&gt;“booksandreviews.com”&lt;/em&gt; will serve as a good example application.&lt;/p&gt;

&lt;p&gt;Given a controller that can create &lt;code class=&quot;highlighter-rouge&quot;&gt;Authors&lt;/code&gt;, a default pattern without Strong Parameters could look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# POST /authors&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;notice: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Author was successfully created.&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;author_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Assuming that there are no presence validations on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; class itself (or in the form view creating this model), this code has no check to make sure that anything about an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; is passed in to create.&lt;/p&gt;

&lt;p&gt;This means that any &lt;code class=&quot;highlighter-rouge&quot;&gt;POST&lt;/code&gt; request is made to &lt;code class=&quot;highlighter-rouge&quot;&gt;/authors&lt;/code&gt; will create a new &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;. While this kind of problem would most likely not make it to production, let us assume that the poor people over at “booksandreviews.com” came from such humble code beginnings that this &lt;strong&gt;was&lt;/strong&gt; the first iteration of the &lt;code class=&quot;highlighter-rouge&quot;&gt;AuthorsController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make the &lt;code class=&quot;highlighter-rouge&quot;&gt;AuthorsController&lt;/code&gt; more robust, the &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt; method can be used on the &lt;code class=&quot;highlighter-rouge&quot;&gt;params&lt;/code&gt; hash:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;author_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now if a &lt;code class=&quot;highlighter-rouge&quot;&gt;POST&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;/authors&lt;/code&gt; does not contain a payload with an &lt;code class=&quot;highlighter-rouge&quot;&gt;:author&lt;/code&gt; key in the body, the request will error:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ActionController::ParameterMissing&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, a request with the &lt;code class=&quot;highlighter-rouge&quot;&gt;:author&lt;/code&gt; attribute will…&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel::ForbiddenAttributesError&lt;/code&gt; &lt;em&gt;Also&lt;/em&gt; cause an error, apparently.&lt;/p&gt;

&lt;p&gt;This is another feature of Strong Parameters. The reason an error occurs is that the &lt;code class=&quot;highlighter-rouge&quot;&gt;author_params&lt;/code&gt; method did not specify which parameters could be mass assigned to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; class. Passing the result of &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt; directly to &lt;code class=&quot;highlighter-rouge&quot;&gt;Author.create&lt;/code&gt; will trip this safety measure.&lt;/p&gt;

&lt;h2 id=&quot;shut-em-down&quot;&gt;Shut ‘em Down&lt;/h2&gt;

&lt;p&gt;To correct the &lt;code class=&quot;highlighter-rouge&quot;&gt;ForbiddenAttributesError&lt;/code&gt; and add some much needed structure to the &lt;code class=&quot;highlighter-rouge&quot;&gt;AuthorsController&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;permit&lt;/code&gt; method needs to be used in conjunction with &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Adding a list of attributes as individual symbols will make sure that only those attributes can be passed through to &lt;code class=&quot;highlighter-rouge&quot;&gt;Author.create!&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;author_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Great! Now a properly formatted &lt;code class=&quot;highlighter-rouge&quot;&gt;POST&lt;/code&gt; containing only the correct attributes will create an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; appropriately.&lt;/p&gt;

&lt;p&gt;But, why go through all the hassle? There should be a way to let all attributes pass, regardless of how crazy harmful they could be to our application we use to pay bills.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;permit!&lt;/code&gt; method is a completely permissive way to allow all attributes to be mass assigned to a model:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;author_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will allow any attributes nested under &lt;code class=&quot;highlighter-rouge&quot;&gt;:author&lt;/code&gt; to be set on an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;. A solution like this requires no declaration of attributes, but is this better?&lt;/p&gt;

&lt;p&gt;The short answer is &lt;em&gt;“no”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The reason why being completely permissive with parameters is a bad idea is because not all attributes were created equally.&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;“booksandreviews.com”&lt;/em&gt; had an &lt;code class=&quot;highlighter-rouge&quot;&gt;admin&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;superuser&lt;/code&gt; column on their &lt;code class=&quot;highlighter-rouge&quot;&gt;authors&lt;/code&gt; table, any &lt;code class=&quot;highlighter-rouge&quot;&gt;POST&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;admin: true&lt;/code&gt; would create not a normal &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;, but an all-mighty &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Specifying the attributes that can be mass assigned to an &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; model is not a new concept, with Strong Parameters this pattern is just too easy not to do.&lt;/p&gt;

&lt;h2 id=&quot;open-up-shop&quot;&gt;Open Up Shop&lt;/h2&gt;

&lt;p&gt;Another great feature of using Strong Parameters is type assertion. Regardless of &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;’s type coercion, ensuring that data is as valid as early as possible is important.&lt;/p&gt;

&lt;p&gt;Consider that an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; can have an array of &lt;code class=&quot;highlighter-rouge&quot;&gt;genres&lt;/code&gt; which summarize their bodies of work. To ensure that this list of &lt;code class=&quot;highlighter-rouge&quot;&gt;genres&lt;/code&gt; is an array, a hash syntax can be used:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;author_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;genres: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;By adding &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;genres:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt; to the end of the &lt;code class=&quot;highlighter-rouge&quot;&gt;permit&lt;/code&gt; call, it ensures that the &lt;code class=&quot;highlighter-rouge&quot;&gt;genres&lt;/code&gt; value is always an array. This prevents random nonsense or a malformed request from compromising the &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; class’ data integrity. If something other than an array is passed as the &lt;code class=&quot;highlighter-rouge&quot;&gt;genres&lt;/code&gt; attribute, it will disregard it.&lt;/p&gt;

&lt;p&gt;Alternatively, when a parameter is a hash (like &lt;code class=&quot;highlighter-rouge&quot;&gt;preferences&lt;/code&gt;), all the keys in the hash need to be present in the &lt;code class=&quot;highlighter-rouge&quot;&gt;permit&lt;/code&gt; call.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-JSON&quot;&gt;{
  &quot;preferences&quot;: {
    &quot;time_zone&quot;: &quot;GMT&quot;,
    &quot;subscribed&quot;: true
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

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

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;author_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;ss&quot;&gt;:country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;preferences: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:time_zone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:subscribed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If this is a tad confusing, check out more examples at the &lt;a href=&quot;https://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters&quot;&gt;official guide for Strong Parameters&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;everything-in-moderation&quot;&gt;Everything in Moderation&lt;/h2&gt;

&lt;p&gt;Strong Parameters is not appropriate for every situation. In the case that a certain number of parameters must be present, or if one parameter must only be present when not accompanied by another specific parameter, Strong Parameters will fall short. The time and place to use Strong Parameters is when creating or updating an &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Additionally, if the Ruby on Rails application in question was an API, Strong Parameters would only be effective in very specific circumstances. Since the feedback given by Strong Parameters is not as granular as an API would like to be, it could be hard to find many uses of it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Validates Type 2.0</title>
   <link href="https://jakeyesbeck.com/2015/11/29/updated-validates-type/"/>
   <updated>2015-11-29T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/11/29/updated-validates-type</id>
   <content type="html">&lt;p&gt;One of the first projects that I worked on during this Year of Commits was &lt;a href=&quot;https://github.com/yez/validates_type&quot;&gt;validates_type&lt;/a&gt;. In case that name is too obscure, &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; is a gem for validating that a specific value is exactly the type it is expected to be. The &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; library is compatible to &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel&lt;/code&gt; style validations.&lt;/p&gt;

&lt;p&gt;Originally, the &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; gem was very strict with what it validated against. It started with basic included Ruby types like &lt;code class=&quot;highlighter-rouge&quot;&gt;Integer&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Float&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt;. This was a fine first step but proved too restrictive for basically any use case.&lt;/p&gt;

&lt;p&gt;In a recent update, the &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; gem has been extended to validate against any defined type in a system. With this update, the uses of this gem greatly increased. They increased so much that it is possible more than 2 people will use it, and that would be pretty awesome.&lt;/p&gt;

&lt;h2 id=&quot;still-valid&quot;&gt;Still Valid&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; gem can be useful for a system that cares about exact types at save time. For instance, a model that has an incorrect database column type (because of legacy or other reasons) can still control validation over its data just the same.&lt;/p&gt;

&lt;p&gt;If a “junior developer who is now somehow the CTO” created the original system. And if that developer did something like create an  &lt;code class=&quot;highlighter-rouge&quot;&gt;is_published&lt;/code&gt; column on the &lt;code class=&quot;highlighter-rouge&quot;&gt;authors&lt;/code&gt; table set as a &lt;code class=&quot;highlighter-rouge&quot;&gt;varchar&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; makes that less of an issue.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates_type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:is_published&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:boolean&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If someone tries to assign a nonsense value to the &lt;code class=&quot;highlighter-rouge&quot;&gt;is_published&lt;/code&gt; attribute, &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; will ensure it does not save.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: callback skipping methods will still save bad values, just like any other &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; validators.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;Author id: nil, name: nil, created_at: nil, updated_at: nil, is_published: nil&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_published&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;foo&#39;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;foo&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; ActiveRecord::RecordInvalid: Validation failed: is_published is expected to be a Boolean and is not.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This way, there is not a bunch of random data in the &lt;code class=&quot;highlighter-rouge&quot;&gt;authors&lt;/code&gt; table because of a bad decision made a while ago. More examples on how this gem can be used are found at the &lt;a href=&quot;https://jakeyesbeck.com/2015/05/10/validates-type/&quot;&gt;prequel to this post&lt;/a&gt; and the &lt;a href=&quot;https://github.com/yez/validates_type/blob/master/README.md&quot;&gt;project’s README&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-new-hotness&quot;&gt;The New Hotness&lt;/h2&gt;

&lt;p&gt;The 2.0 update brought flexibility to &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt;. This enables greater control over serialized attributes on &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;In a system with an intermediary class inserted between the column assignment and the column serialization, this extension can show its true value.&lt;/p&gt;

&lt;p&gt;In an application that deals with &lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt;, each book must store information regarding how it was published:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;serialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:publishing_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PublishingInformation&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Perhaps each book can have such a variety of publishing information, or the data present can vary widely between each book. Whatever the reason, we can assume that the &lt;code class=&quot;highlighter-rouge&quot;&gt;PublishingInformation&lt;/code&gt; class handles the input and extraction of the &lt;code class=&quot;highlighter-rouge&quot;&gt;JSON&lt;/code&gt; data pertinent to a specific &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that assumption, an issue could arise if another type of object was assigned to a &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;publishing_information&lt;/code&gt; column.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;publishing_information&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foo: :bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; UPDATE &quot;books&quot; SET &quot;publishing_information&quot; = $1, &quot;updated_at&quot; = $2 WHERE &quot;books&quot;.&quot;id&quot; = $3  [[&quot;publishing_information&quot;, &quot;{}&quot;], [&quot;updated_at&quot;, &quot;2015-11-30 05:04:09.480707&quot;], [&quot;id&quot;, 3]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If, like the above example, the &lt;code class=&quot;highlighter-rouge&quot;&gt;PublishingInformation&lt;/code&gt; class is forgiving, this will silently fail. The &lt;code class=&quot;highlighter-rouge&quot;&gt;book.publishing_information&lt;/code&gt; will not be set to the correct value.&lt;/p&gt;

&lt;p&gt;On the other hand, if the &lt;code class=&quot;highlighter-rouge&quot;&gt;PublishingInformation&lt;/code&gt; does fail, it might not do so in an obvious way.&lt;/p&gt;

&lt;p&gt;However, with &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt;, this issue becomes explicit.&lt;/p&gt;

&lt;p&gt;Adding the type validation to the book model:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;serialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:publishing_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PublishingInformation&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates_type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:publishing_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PublishingInformation&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then the same &lt;code class=&quot;highlighter-rouge&quot;&gt;save!&lt;/code&gt; call gives a different error:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;publishing_information&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;a: :b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; ActiveRecord::RecordInvalid: Validation failed: publishing_information is expected to be a PublishingInformation and is not.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, a readable error is produced and nothing is left to the imagination.&lt;/p&gt;

&lt;h2 id=&quot;a-reasonable-start&quot;&gt;A Reasonable Start&lt;/h2&gt;

&lt;p&gt;Was the used example extremely specific? Yes. But, I would wager that at least one application out there has had a problem similar to this and &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_type&lt;/code&gt; can ensure that it never happens again. Hopefully, this example and the problem it did end up solving with at least act as inspiration for this library’s other uses out in the wild.&lt;/p&gt;

&lt;p&gt;I have found a use for this type of validation and hope others can as well. If a use case arises that this gem does not support but could easily, &lt;a href=&quot;https://github.com/yez/validates_type&quot;&gt;I invite everyone to contribute to it&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>How to Write Future-proof Mocks in RSpec 3</title>
   <link href="https://jakeyesbeck.com/2015/11/22/how-to-write-futureproof-mocks/"/>
   <updated>2015-11-22T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/11/22/how-to-write-futureproof-mocks</id>
   <content type="html">&lt;p&gt;Tests are an important component in most software applications. Whether tests drive the development, or are strapped on after the fact, tests need to be reliable for future development to progress. An application’s complexity rises with time. During and after this increase, a rock solid test suite is crucial.&lt;/p&gt;

&lt;h2 id=&quot;let-the-dogs-out&quot;&gt;Let the Dogs Out&lt;/h2&gt;

&lt;p&gt;Given an application that deals with &lt;code class=&quot;highlighter-rouge&quot;&gt;Dogs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Keeping track of grooming statistics about this application’s dogs is the obvious cash cow. But that sounds very tedious and complicated, so we can assume that a &lt;code class=&quot;highlighter-rouge&quot;&gt;GroomingService&lt;/code&gt; exists that exposes a single &lt;code class=&quot;highlighter-rouge&quot;&gt;Groomer&lt;/code&gt; object:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;GroomingService&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Groomer&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;groom&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Some complex grooming logic&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This service was included by the &lt;code class=&quot;highlighter-rouge&quot;&gt;groomer&lt;/code&gt; gem and will become a core piece of the application. To keep everyone in the project sane and well rested, a robust spec suite is needed.&lt;/p&gt;

&lt;h2 id=&quot;spec-it-up&quot;&gt;Spec It Up&lt;/h2&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;RSpec&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;GroomingService&lt;/code&gt;, a very basic test can be written to make sure the code works as expected.&lt;/p&gt;

&lt;p&gt;Introducing the &lt;code class=&quot;highlighter-rouge&quot;&gt;GroomingService&lt;/code&gt; into the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class could look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;groom&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;GroomingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;groom&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The first test should be to make sure that when the &lt;code class=&quot;highlighter-rouge&quot;&gt;groom&lt;/code&gt; method on a &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; is called, it initializes and calls &lt;code class=&quot;highlighter-rouge&quot;&gt;groom&lt;/code&gt; out to the &lt;code class=&quot;highlighter-rouge&quot;&gt;GroomService::Groomer&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;When asserting that a certain set of methods is called on a particular object, the built in &lt;a href=&quot;https://www.relishapp.com/rspec/rspec-mocks/v/3-4/docs/basics/test-doubles&quot;&gt;RSpec double&lt;/a&gt; method is very handy.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;double&lt;/code&gt; method returns a stand-in object to assert &lt;code class=&quot;highlighter-rouge&quot;&gt;allow&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;expect&lt;/code&gt; messages against. Any method that is called on the test double which is not explicitly &lt;code class=&quot;highlighter-rouge&quot;&gt;allow&lt;/code&gt;ed or &lt;code class=&quot;highlighter-rouge&quot;&gt;expect&lt;/code&gt;ed results in an error.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;described_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#groom&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GroomingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;initializes and calls groom&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GroomingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;groomer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:groom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;groom&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As expected, this test passes beautifully:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec dog_spec.rb

Dog
  &lt;span class=&quot;c&quot;&gt;#groom&lt;/span&gt;
    calls new with self and &lt;span class=&quot;k&quot;&gt;then &lt;/span&gt;groom

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00773 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.09367 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 0 failures

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

&lt;p&gt;That can be it, right? Pack it up and put the dogs away, whoever let them out will have to do it all again later.&lt;/p&gt;

&lt;h2 id=&quot;think-of-the-future&quot;&gt;Think of the Future&lt;/h2&gt;

&lt;p&gt;After some time passes, the &lt;code class=&quot;highlighter-rouge&quot;&gt;GroomingService::Groomer&lt;/code&gt; has changed its method signature. Instead of the &lt;code class=&quot;highlighter-rouge&quot;&gt;groom&lt;/code&gt; method, it has changed to &lt;code class=&quot;highlighter-rouge&quot;&gt;groom!&lt;/code&gt;. Chances are someone thought that either the method had too many side affects or that &lt;code class=&quot;highlighter-rouge&quot;&gt;!&lt;/code&gt; are just really awesome looking.&lt;/p&gt;

&lt;p&gt;In any case, the included service changes and when the test runs:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec dog_spec.rb

Dog
  &lt;span class=&quot;c&quot;&gt;#groom&lt;/span&gt;
    calls new with self and &lt;span class=&quot;k&quot;&gt;then &lt;/span&gt;groom

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00735 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.10532 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 0 failures

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

&lt;p&gt;&lt;em&gt;It passes&lt;/em&gt;? How can that be? The method changed from &lt;code class=&quot;highlighter-rouge&quot;&gt;groom&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;groom!&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;groom&lt;/code&gt; method does not even exist on &lt;code class=&quot;highlighter-rouge&quot;&gt;GroomingService::Groomer&lt;/code&gt;. It seems that the specs do not care what does or does not exist on the &lt;code class=&quot;highlighter-rouge&quot;&gt;double&lt;/code&gt;, they just happily pass.&lt;/p&gt;

&lt;h2 id=&quot;use-instancedouble&quot;&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_double&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The answer here is to use &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_double&lt;/code&gt;. Like &lt;code class=&quot;highlighter-rouge&quot;&gt;double&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_double&lt;/code&gt; also returns a stand-in object that raises errors if methods not &lt;code class=&quot;highlighter-rouge&quot;&gt;allow&lt;/code&gt;ed or &lt;code class=&quot;highlighter-rouge&quot;&gt;expect&lt;/code&gt;ed are called on the object.&lt;/p&gt;

&lt;p&gt;The key difference is that &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_double&lt;/code&gt; checks the underlying object to make sure that it responds to methods before making assertions that they are called.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;described_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#groom&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instance_double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GroomingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;initializes and calls groom&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GroomingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;groomer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:groom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;groom&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now running this test, we see the failure we should expect:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; rspec dog_spec.rb

Dog
  &lt;span class=&quot;c&quot;&gt;#groom&lt;/span&gt;
    calls new with self and &lt;span class=&quot;k&quot;&gt;then &lt;/span&gt;groom &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;FAILED - 1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

Failures:

  1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Dog#groom calls new with self and &lt;span class=&quot;k&quot;&gt;then &lt;/span&gt;groom
     Failure/Error: expect&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;groomer&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.to receive&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;:groom&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
       the GroomingService::Groomer class does not
          implement the instance method: groom

Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.0054 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.08288 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1 example, 1 failure
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;While no one likes failing specs, a failure here is always preferable to one in production.&lt;/p&gt;

&lt;p&gt;Since the API that we do not own (&lt;code class=&quot;highlighter-rouge&quot;&gt;Groomer&lt;/code&gt;) changed, it was a mistake to blindly mock it without asking the underlying object if that method existed. However, with this problem corrected, the code is more robust and development can continue.&lt;/p&gt;

&lt;h2 id=&quot;mocking-with-confidence&quot;&gt;Mocking with Confidence&lt;/h2&gt;

&lt;p&gt;Asserting that a method is called on an object is a very common pattern in Ruby tests. Additionally, Ruby does not have the benefit of compiled languages in terms of method invocation validation. We as Rubyists rely on automated testing to make sure that our applications work as expected, can be iterated upon, and handle third party library updates. While it may be attractive to use permissive mocking assertions, they can be dangerous and cause more problems than they are worth.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Five Active Record Features You Should Be Using</title>
   <link href="https://jakeyesbeck.com/2015/11/15/five-active-record-features-you-should-be-using/"/>
   <updated>2015-11-15T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/11/15/five-active-record-features-you-should-be-using</id>
   <content type="html">&lt;p&gt;Active Record is responsible for communicating with the persistence layer by default in Ruby on Rails applications. Using Active Record effectively and efficiently can greatly improve an application’s code.&lt;/p&gt;

&lt;p&gt;In Ruby on Rails 4.0, some material changes have been made to Active Record. Understanding these changes, and how they are best utilized is important for any Rails developer.&lt;/p&gt;

&lt;p&gt;To help explain these concepts, we can assume a Ruby on Rails application &lt;em&gt;“booksandreviews.com”&lt;/em&gt; exists with three models:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:reviews&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:books&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:book&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The smart people over at &lt;em&gt;“booksandreviews.com”&lt;/em&gt; need to know what the state of their data to build metrics and make sales. Metrics need data and Active Record will be used to fetch that data.&lt;/p&gt;

&lt;h2 id=&quot;nested-queries&quot;&gt;1. Nested Queries&lt;/h2&gt;

&lt;p&gt;When doing database queries, the fewer the better. Since Active Record is responsible of crafting these queries, it is important to make sure it has all the help it needs. For simple queries this is rarely an issue, but more complex requirements can lead to sub-optimal results.&lt;/p&gt;

&lt;p&gt;One day, Tim from sales comes rampaging through the office convinced that there &lt;strong&gt;must&lt;/strong&gt; be a bug in the system. A recent sale for &lt;em&gt;“booksandreviews.com”&lt;/em&gt; did not go well and he wants answers. Tim wants an analysis run. He wants all reviews published today, which are for books published in 2015.&lt;/p&gt;

&lt;p&gt;Without too much thought, this approach seems reasonable:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;book_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_year: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2015&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;books&quot;.* FROM &quot;books&quot; WHERE (publish_year = &#39;2015&#39;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;reviews&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_date: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2015-11-15&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;ss&quot;&gt;book_ids: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;reviews&quot;.* FROM &quot;reviews&quot; WHERE &quot;reviews&quot;.&quot;publish_date&quot; = &#39;2015-11-15&#39; AND &quot;reviews&quot;.&quot;book_ids&quot; IN (1, 2, 3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will load the desired books, extract their &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt;’s, and pass that result to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; query. Not only does this generate two queries, it also wastes memory by creating an array of &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; objects to &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt; over and then another array of &lt;code class=&quot;highlighter-rouge&quot;&gt;book_ids&lt;/code&gt;. With a large enough list of books, this could cause some serious problems.&lt;/p&gt;

&lt;p&gt;Active Record’s &lt;code class=&quot;highlighter-rouge&quot;&gt;where&lt;/code&gt; method returns an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord::Relation&lt;/code&gt;. These relations can be passed to other methods to aid in query construction. With the same request, we can save the &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt; and array creation:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_year: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2015&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; ActiveRecord::Relation&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;reviews&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_date: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2015-11-15&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;book: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# SELECT &quot;reviews&quot;.* FROM &quot;reviews&quot; WHERE &quot;reviews&quot;.&quot;publish_date&quot; = &#39;2015-11-15&#39; AND &quot;reviews&quot;.&quot;book_id&quot; IN (SELECT &quot;books&quot;.&quot;id&quot; FROM &quot;books&quot; WHERE &quot;books&quot;.&quot;publish_year&quot; = &#39;2015&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This still executes two &lt;code class=&quot;highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; statements but it nests them to let the database take care of memory allocation and optimization. The &lt;code class=&quot;highlighter-rouge&quot;&gt;book_ids&lt;/code&gt; array is replaced with the &lt;code class=&quot;highlighter-rouge&quot;&gt;books&lt;/code&gt; relation and is passed to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: This can reduced to a single query with &lt;code class=&quot;highlighter-rouge&quot;&gt;.joins&lt;/code&gt;, but for now we can assume that a nested query is desired.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;dry-scopes&quot;&gt;2. DRY Scopes&lt;/h2&gt;

&lt;p&gt;Still fuming, Tim demands more information. Now he wants to know the list of all &lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt; published in 2015 which have at least one approved &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt;. Since &lt;code class=&quot;highlighter-rouge&quot;&gt;Reviews&lt;/code&gt; are subjective, they need to be approved in order to maintain the quality that &lt;em&gt;“booksandreviews.com”&lt;/em&gt; is known for.&lt;/p&gt;

&lt;p&gt;Luckily, a scope has been written on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; class to accomplish this.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:book&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:approved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;approved: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;However, it is &lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt; that we need to return, not &lt;code class=&quot;highlighter-rouge&quot;&gt;Reviews&lt;/code&gt;. Repeating the scope definition, a join query can be used for this analysis:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_year: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2015&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;references&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;reviews.approved = ?&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT #long books and reviews column select# FROM &quot;books&quot; LEFT OUTER JOIN &quot;reviews&quot; ON &quot;reviews&quot;.&quot;book_id&quot; = &quot;books&quot;.&quot;id&quot; WHERE &quot;books&quot;.&quot;publish_year&quot; = &#39;2015&#39; AND (reviews.approved = &#39;t&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Books&lt;/code&gt; are returned at the cost of duplicating the &lt;code class=&quot;highlighter-rouge&quot;&gt;approved&lt;/code&gt; scope. That means that the scope in &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; changes, this code will not benefit from that change. The &lt;code class=&quot;highlighter-rouge&quot;&gt;.includes&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;.references&lt;/code&gt; methods are used to ensure that we only return one &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; (in the case of many &lt;code class=&quot;highlighter-rouge&quot;&gt;Reviews&lt;/code&gt; belonging to the same &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;D&lt;/strong&gt;on’t &lt;strong&gt;R&lt;/strong&gt;epeat &lt;strong&gt;Y&lt;/strong&gt;ourself (DRY) principle was created for this exact reason. When identical code is not shared and instead repeated, changes to one version can have dangerous consequences on the other.&lt;/p&gt;

&lt;p&gt;The good news is that Active Record provides precisely the medicine for this ailment: &lt;code class=&quot;highlighter-rouge&quot;&gt;.merge&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;code class=&quot;highlighter-rouge&quot;&gt;.merge&lt;/code&gt;, an existing scope can be used in another Active Record query.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_year: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2015&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;references&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;approved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT #long books and reviews column select# FROM &quot;books&quot; LEFT OUTER JOIN &quot;reviews&quot; ON &quot;reviews&quot;.&quot;book_id&quot; = &quot;books&quot;.&quot;id&quot; WHERE &quot;books&quot;.&quot;publish_year&quot; = &#39;2015&#39; AND (reviews.approved = &#39;t&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Great! Now the results are the exact same and the code is DRY.&lt;/p&gt;

&lt;h2 id=&quot;wherenot&quot;&gt;3. &lt;code class=&quot;highlighter-rouge&quot;&gt;where.not&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Typical insatiable Tim is back with yet another request to add to the brand new “totally not vanity metrics dashboard”. Now, he wants to know all the books &lt;strong&gt;not&lt;/strong&gt; published in 2012.&lt;/p&gt;

&lt;p&gt;Without even asking why such a silly request is necessary, some more code can be cranked out:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;publish_year != 2012&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;books&quot;.* FROM &quot;books&quot; WHERE (publish_year != &#39;2012&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Like before, this code works but could be better. There is some raw SQL in there that the next developer might not understand well enough to manipulate. Whatever the reason, it is best to rely on abstraction instead of explicit SQL.&lt;/p&gt;

&lt;p&gt;To help solve this dilemma, the &lt;code class=&quot;highlighter-rouge&quot;&gt;.not&lt;/code&gt; modifier has been introduced in Active Record 4.0.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;publish_year: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2012&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT &quot;books&quot;.* FROM &quot;books&quot; WHERE (publish_year != &#39;2012&#39;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The result is the same but look how much nicer that is. Not only is the raw SQL gone, the code is more positive too.&lt;/p&gt;

&lt;h2 id=&quot;first-and-take&quot;&gt;4. &lt;code class=&quot;highlighter-rouge&quot;&gt;first&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;take&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Since &lt;em&gt;“booksandreviews.com”&lt;/em&gt; has been around since 2012, chances are it upgraded from Ruby on Rails 3.0 to 4.0. One notable change from Active Record 3 to 4 is the behaviour of &lt;code class=&quot;highlighter-rouge&quot;&gt;.first&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Ruby on Rails 4.0+, the &lt;code class=&quot;highlighter-rouge&quot;&gt;.first&lt;/code&gt; method returns the first row after the table has been ordered by its &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Bill&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT  &quot;authors&quot;.* FROM &quot;authors&quot; WHERE &quot;authors&quot;.&quot;first_name&quot; = &quot;Bill&quot; ORDER BY &quot;authors&quot;.&quot;id&quot; ASC LIMIT 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will work fine for every table that has an &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; column. However, if a table does not need an &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; column, this method causes a problem.&lt;/p&gt;

&lt;p&gt;Despite each &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; having an id, complex joins might cause an issue with an implicit &lt;code class=&quot;highlighter-rouge&quot;&gt;ORDER BY&lt;/code&gt; on queries.&lt;/p&gt;

&lt;p&gt;To alleviate that problem, the &lt;code class=&quot;highlighter-rouge&quot;&gt;take&lt;/code&gt; method can be used instead of &lt;code class=&quot;highlighter-rouge&quot;&gt;first&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Bill&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;take&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; SELECT  &quot;authors&quot;.* FROM &quot;authors&quot; WHERE &quot;authors&quot;.&quot;first_name&quot; = &quot;Bill&quot; LIMIT 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This behaves in a much more explicit way, returning the same information without a default ordering.&lt;/p&gt;

&lt;h2 id=&quot;unscoped&quot;&gt;5. &lt;code class=&quot;highlighter-rouge&quot;&gt;.unscoped&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;During the development life of “&lt;em&gt;booksandreviews.com”&lt;/em&gt;, countless modules have been built and gems included. Amidst this chaos, someone must have typed &lt;code class=&quot;highlighter-rouge&quot;&gt;gem install hairball&lt;/code&gt; and horribly altered the &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; class. This has led to the new guy Mike’s  complaint that: &lt;em&gt;“Authors are missing data”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Mike knows that authors have a &lt;code class=&quot;highlighter-rouge&quot;&gt;first_name&lt;/code&gt; but for some reason it is not being returned:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;authors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Smith&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;take&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;authors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [nil, nil, nil, nil, nil]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;What Mike does not know is that one of those hairball gems added a default scope to all Active Record objects that begin with the letter “A”. However impossible this bug is, it exists and it is ruining Mike’s day.&lt;/p&gt;

&lt;p&gt;What Mike needs is the &lt;code class=&quot;highlighter-rouge&quot;&gt;.unscoped&lt;/code&gt; method. This method removes all existing scopes on an Active Record relation.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;authors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unscoped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Smith&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;take&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;authors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [&#39;Frank&#39;, &#39;Frank&#39;, &#39;Jim&#39;, &#39;Frank&#39;, &#39;Frank&#39;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(Is anyone else concerned that there are four Frank Smith authors?)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the &lt;code class=&quot;highlighter-rouge&quot;&gt;.unscoped&lt;/code&gt; method, all harmful default scopes are removed and the Franks are free.&lt;/p&gt;

&lt;h2 id=&quot;queries-on-queries&quot;&gt;Queries on Queries&lt;/h2&gt;

&lt;p&gt;With these five techniques (and probably a lot more), naiive Active Record queries can stay DRY and intuitive. The exhaustive list of what Active Record can provide can be found &lt;a href=&quot;https://guides.rubyonrails.org/active_record_querying.html&quot;&gt;at Rails Guides&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Ruby DelegateClass</title>
   <link href="https://jakeyesbeck.com/2015/11/08/ruby-delegate-class/"/>
   <updated>2015-11-08T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/11/08/ruby-delegate-class</id>
   <content type="html">&lt;p&gt;Objects are a big deal in Ruby. A &lt;a href=&quot;https://jakeyesbeck.com/2015/08/23/ruby-objects/&quot;&gt;previous post about Ruby Objects&lt;/a&gt; can corroborate: Ruby Objects are pretty cool.&lt;/p&gt;

&lt;p&gt;There are many ways to work with Ruby Objects. Standard inheritance, module inheritance, decorators, and composition are all commonly found in a codebase. One class in particular seems almost universal across applications: the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;From social networks to online retails stores, web applications most always have a &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt;. Additionally, the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class might interact with nearly all other classes. This can make the relationship and responsibilities of that &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; awkward or unwieldy over time.&lt;/p&gt;

&lt;p&gt;As an example, assume that an application &lt;em&gt;“booksandreviews.com”&lt;/em&gt; exists. This application serves both authors and critics, each representing a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;. These &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; types have different responsibilities and privileges.&lt;/p&gt;

&lt;p&gt;Assuming a Rails application, the basic user model will look most likely like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;One approach to extend this class and make &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt; classes is to use the Single Table Inheritance pattern. STI is a common pattern in Rails applications to share responsibilities between classes and store all records in the same place. This approach can work and might fit current needs just fine, but it might be beneficial to think outside the single table for a second.&lt;/p&gt;

&lt;p&gt;After all, no one said a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; had to be either an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; or a &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt;, what if they were both?&lt;/p&gt;

&lt;h2 id=&quot;delegators-mount-up&quot;&gt;Delegators, Mount Up!&lt;/h2&gt;

&lt;p&gt;An alternative way to architect a system like the one described is by using delegation. Object delegation is a way of composing objects to achieve flexibility and maintain encapsulation.&lt;/p&gt;

&lt;p&gt;Ruby provides a few ways to delegate objects. An interesting option that will nicely serve this application’s needs is &lt;a href=&quot;https://ruby-doc.org/stdlib-2.2.1/libdoc/delegate/rdoc/Object.html#method-i-DelegateClass&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DelegateClass&lt;/code&gt;&lt;/a&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;DelegateClass&lt;/code&gt; method accepts a class and returns a new class. The returned class takes the passed in class’s instance methods and defines delegating methods.&lt;/p&gt;

&lt;p&gt;Defining &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt; classes:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DelegateClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Critic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DelegateClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;These classes both expect to be initialized with an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;, then will delegate methods to the passed in &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; by default. This allows each class to define their own logic for determining what an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; or a &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt; has access to.&lt;/p&gt;

&lt;p&gt;Initializing these classes is as simple as loading the &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; then passing it in:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;critic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Critic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;critic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;business-logic&quot;&gt;Business Logic&lt;/h2&gt;

&lt;p&gt;Assuming that &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Review&lt;/code&gt; records exist in this same application, related to a user by a &lt;code class=&quot;highlighter-rouge&quot;&gt;user_id&lt;/code&gt;, both new classes can handle those resources independently.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DelegateClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;written_books&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@written_books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;has_written_books?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;written_books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;present?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;top_selling_book&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;written_books&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:revenue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Critic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DelegateClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;written_reviews&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@written_reviews&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;has_reviewed_book?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;written_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;book_id: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;present?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;top_viewed_review&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;written_reviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:views&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;See how nice it is with the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class responsible only for standard &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; information? That leaves the &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt; classes available to house business logic the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; should not have to concern itself with.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class can keep caring about things like &lt;code class=&quot;highlighter-rouge&quot;&gt;updated_at&lt;/code&gt; timestamps, important booleans like &lt;code class=&quot;highlighter-rouge&quot;&gt;is_a_confirmed_user?&lt;/code&gt;, and any other methods that indicate how a general &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; interacts with the software. Also, it remains the sole responsibility of the &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; to interact with the persistence layer. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt; classes will delegate instance methods like &lt;code class=&quot;highlighter-rouge&quot;&gt;save&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;update&lt;/code&gt; to the underlying &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;adding-yet-another-type&quot;&gt;Adding Yet Another Type&lt;/h2&gt;

&lt;p&gt;Imagine some time passes and &lt;em&gt;“booksandreviews.com”&lt;/em&gt;’s membership is popping off like gangbusters. Then one day, Tim from sales comes down and says: &lt;em&gt;“We are literally making no money, we need to sell these books or something”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Tim is asking for a new use case for the product, a new type of &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; will be needed: the &lt;code class=&quot;highlighter-rouge&quot;&gt;Consumer&lt;/code&gt;. As before, a &lt;code class=&quot;highlighter-rouge&quot;&gt;Consumer&lt;/code&gt; could be an &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt;, both, or neither.&lt;/p&gt;

&lt;p&gt;Had this application been built with STI, I would wager some spaghetti code would form trying, to shoehorn the same user into three roles.&lt;/p&gt;

&lt;p&gt;However, with the &lt;code class=&quot;highlighter-rouge&quot;&gt;DelegateClass&lt;/code&gt; pattern we have used, it becomes trivial:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Consumer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DelegateClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transactions&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@purchased_books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;purchaed_books&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transactions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;needs_marketing_email?&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Tim says we need to email people to &quot;encourage&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#  them into buying things.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transactions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now this new class can be utilized to spam the users of &lt;em&gt;“booksandreviews.com”&lt;/em&gt; until Tim is content.&lt;/p&gt;

&lt;p&gt;An important note is that instances of &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;Consumer&lt;/code&gt; are not instances of &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;keeping-it-closed&quot;&gt;Keeping it Closed&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;DelegateClass&lt;/code&gt; approach keeps the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class &lt;a href=&quot;https://en.wikipedia.org/wiki/Open/closed_principle&quot;&gt;open to extension but closed for modification&lt;/a&gt;. Adhering to this principle becomes very beneficial if the backing of the &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; model changes.&lt;/p&gt;

&lt;p&gt;Maybe in the future, &lt;em&gt;“booksandreviews.com”&lt;/em&gt; experiences astronomical growth, resulting in a huge service oriented architecture overhaul. Suddenly, a &lt;code class=&quot;highlighter-rouge&quot;&gt;UserService&lt;/code&gt; exists which communicates with an internal API. If that happens, our code is safe.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Author&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Critic&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;Consumer&lt;/code&gt; classes need not change:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_user_by_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;consumer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Consumer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;consumer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As previously stated, there are many ways to solve this particular problem. Arguments for module inheritance or single table inheritance could be made and might result in just as valid solutions.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Six Months of Commits</title>
   <link href="https://jakeyesbeck.com/2015/11/01/six-months-of-commits/"/>
   <updated>2015-11-01T07:00:00-05:00</updated>
   <id>https://jakeyesbeck.com/2015/11/01/six-months-of-commits</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/180_day_streak.png&quot; alt=&quot;180 Days of Commits&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Six months ago I started &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;a challenge for myself&lt;/a&gt;. I wanted to contribute to open source software, a task that I had previously thought out of reach and intimidating. A plan that I had devised to overcome this mindset was to achieve consistency. For a full year, I made a commitment to make at least one commit to an open source repository (someone else’s or my own) every single day. Additionally, I decided to write an article every Sunday about either my projects, my journey, or something interesting I encountered along the way.&lt;/p&gt;

&lt;p&gt;To be honest, I did not give my original goal all that much thought. I primarily was making a hypothesis: &lt;em&gt;“If I just keep doing something, chances are that I will improve”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Looking back, I believe that I have improved. How much I have improved has been hard to measure, but the journey itself has helped me understand the real value I was gaining. However, only after reflecting on my progress could I really understand that there was an at all.&lt;/p&gt;

&lt;h2 id=&quot;re-visit&quot;&gt;Re-visit&lt;/h2&gt;

&lt;p&gt;Routines and patterns enable unintentional autopilot. The drive to work, the morning coffee run, even the same weekly meeting are examples of every day life patterns. Can one really distinguish between their commute last Wednesday versus the previous? When our brain does the same thing over and over, it automatically optimizes itself. We forget the details about our days and what distinguishes them from one another. This year of commits project has been no different. Since I have been writing software every single day, I find myself with another daily pattern.&lt;/p&gt;

&lt;p&gt;I am lucky that this project exists in a world where history is king. From Github to Google, I have the ability to rewind time and watch my journey step by step. While some days have been lighter than others, the overall picture is clear: This has been one of the best things I have done for my professional development and my state of mind. I might have not noticed this development unless I took my own advice: &lt;a href=&quot;https://jakeyesbeck.com/2015/09/06/stop-and-take-a-moment/&quot;&gt;to stop to take a moment&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;persevere&quot;&gt;Persevere&lt;/h2&gt;

&lt;p&gt;There have been a number of surprises during the last six months. A few commits were done right at the wire, racing against midnight. Others felt like they took the entire day to complete. Additionally, I have experienced a few very hard times. Days that sapped all motivation for writing code. But so far, I have not missed a single day. I think that if I had missed one day, it would be simple to miss multiple. For now, I am still in a streak which is helpfully demonstrated on Github. Internalizing this perseverance has been crucial.&lt;/p&gt;

&lt;p&gt;Repeat actions build confidence. I remember at the onset of this project, the first pull request that I did to a new repository had me literally shaking. I must have read each commit message text twenty times before pressing the “Open Pull Request” button. Now, with many pull requests successfully merged, the previous anxiety has vanished. Confidence in the correct quantities can be extremely powerful. This confidence has helped me develop my technical skills and has been instrumental for receiving feedback and criticism.&lt;/p&gt;

&lt;h2 id=&quot;thanks&quot;&gt;Thanks&lt;/h2&gt;

&lt;p&gt;A person who I hold in high regard recently said they found my effort inspiring. I never intended for this endeavor to yield glory or admiration; but, few things are more motivating than hearing kind words of encouragement. To know that I have not been shouting in a dark room and that my effort has meant something feels amazing.&lt;/p&gt;

&lt;p&gt;To all the people who have been supportive and hopefully will continue to do so, you are the reason that I am gaining so much out of this experience. You are the reason I will continue this path forward. You are the reason I will complete a Year of Commits.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Traverse Foreign Ruby Code</title>
   <link href="https://jakeyesbeck.com/2015/10/25/how-to-traverse-foreign-ruby-code/"/>
   <updated>2015-10-25T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/10/25/how-to-traverse-foreign-ruby-code</id>
   <content type="html">&lt;p&gt;A Ruby on Rails project will most likely contain large amounts of third party software. Software written by other people can fluctuate greatly in terms of documentation. Even very well documented software might have pieces that are more shrouded than others.&lt;/p&gt;

&lt;p&gt;When these opaque pieces of code start to cause issue or incite curiosity, spelunking through these libraries is easier with simple patterns and the right tools.&lt;/p&gt;

&lt;h2 id=&quot;get-the-right-tools&quot;&gt;0. Get the Right Tools&lt;/h2&gt;

&lt;p&gt;An important piece of technology when reading code is a text editor. The right editor will make searching for methods fast and opening files painless.&lt;/p&gt;

&lt;p&gt;Another vital component when traversing Ruby code is a runtime debugger. For this, the &lt;a href=&quot;https://github.com/pry/pry&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;pry&lt;/code&gt; gem&lt;/a&gt; is a personal favorite. Using &lt;code class=&quot;highlighter-rouge&quot;&gt;pry&lt;/code&gt; is as simple as requiring it, then adding &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; at the desired stopping point. Alternatively, some people like to debug with output statements in code execution; but, this is 2015 and I like things that I can interact with.&lt;/p&gt;

&lt;h2 id=&quot;use-source-and-sourcelocation&quot;&gt;1. Use &lt;code class=&quot;highlighter-rouge&quot;&gt;source&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;source_location&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;This example will use &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt; method as the subject of investigation.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt; method is useful for storing data with a volatile structure. If an application wants to prototype a feature or is unsure about how useful a certain data structure might be, using &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt; is reasonable. In this case we can assume that the &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt; column is the &lt;code class=&quot;highlighter-rouge&quot;&gt;json&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;Given a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class, with a column named &lt;code class=&quot;highlighter-rouge&quot;&gt;settings&lt;/code&gt;, we can define two  &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessors&lt;/code&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;is_registered&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;contact_method&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;store_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:is_registered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:contact_method&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This model responds to &lt;code class=&quot;highlighter-rouge&quot;&gt;contact_method=&lt;/code&gt; and serializes the result into the &lt;code class=&quot;highlighter-rouge&quot;&gt;json&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;If we wanted to see how this was defined, we need to start a console and look at where the &lt;code class=&quot;highlighter-rouge&quot;&gt;contact_method=&lt;/code&gt; method exists.&lt;/p&gt;

&lt;p&gt;To see the definition of a method, &lt;code class=&quot;highlighter-rouge&quot;&gt;method&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;source&lt;/code&gt; are helpful.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:contact_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; define_method(&quot;#{key}=&quot;) do |value|&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     write_store_attribute(store_attribute, key, value)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It seems that the &lt;code class=&quot;highlighter-rouge&quot;&gt;contact_method=&lt;/code&gt; method is meta-programmed. This does not say much but gives a good starting point. Now, to find which file this method is defined in, &lt;code class=&quot;highlighter-rouge&quot;&gt;source_location&lt;/code&gt; is used.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:contact_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source_location&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&quot;$RVM_PATH/.rvm/gems/ruby-2.2.1@global/gems/activerecord-4.2.4/lib/active_record/store.rb&quot;, 85]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As assumed, the method which defines the &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt; methods is inside of &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;, specifically on line &lt;code class=&quot;highlighter-rouge&quot;&gt;85&lt;/code&gt; of &lt;code class=&quot;highlighter-rouge&quot;&gt;store.rb&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;place-a-reasonable-bindingpry&quot;&gt;2. Place a Reasonable &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;With the location of the method found, &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; has a logical place to go. Since &lt;a href=&quot;https://jakeyesbeck.com/2015/08/16/gems-are-not-magic/&quot;&gt;gems are not magic&lt;/a&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; gem can be opened and its source easily read. Opening gems is fairly simple, set a desired &lt;code class=&quot;highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; and open via the &lt;code class=&quot;highlighter-rouge&quot;&gt;bundle&lt;/code&gt; command. For this example, &lt;code class=&quot;highlighter-rouge&quot;&gt;subl&lt;/code&gt; is mapped to Sublime Text.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;EDITOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;subl bundle open activerecord
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then, navigating to line &lt;code class=&quot;highlighter-rouge&quot;&gt;85&lt;/code&gt; of &lt;code class=&quot;highlighter-rouge&quot;&gt;store.rb&lt;/code&gt;, a &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; can be added to stop code execution when the &lt;code class=&quot;highlighter-rouge&quot;&gt;contact_method=&lt;/code&gt; method is used.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# In activerecord-4.2.4/lib/active_record/store.rb&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pry&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:contact_method&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pry&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note: adding &lt;code class=&quot;highlighter-rouge&quot;&gt;require &#39;pry&#39;&lt;/code&gt; might not be necessary, depending on the bundle this code is running in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; in place, launching a new &lt;code class=&quot;highlighter-rouge&quot;&gt;rails console&lt;/code&gt; will use the modified code. When a &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;contact_method=&lt;/code&gt; method is called, pry will take over.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;contact_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;phone: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;86&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pry&#39;&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;87&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:contact_method&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;88&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pry&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;89&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;91&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We have liftoff! The code is halted in the meta programmed definition of this setter. The local variables here can be accessed to see what is actually going on:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; :settings&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {:phone=&amp;gt;true}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; :contact_method&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This tells us some, but it seems that the real logic is in the &lt;code class=&quot;highlighter-rouge&quot;&gt;write_store_attribute&lt;/code&gt; method. While the code execution is stopped, we are able to use the same &lt;code class=&quot;highlighter-rouge&quot;&gt;method().source&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;method().source_location&lt;/code&gt; calls from before to gain even more insight.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; def write_store_attribute(store_attribute, key, value)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt;   accessor = store_accessor_for(store_attribute)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt;   accessor.write(self, store_attribute, key, value)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; end&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source_location&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&quot;$RVM_PATH/.rvm/gems/ruby-2.2.1@global/gems/activerecord-4.2.4/lib/active_record/store.rb&quot;,&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;129&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

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

&lt;h2 id=&quot;make-an-exit&quot;&gt;3. Make an Exit&lt;/h2&gt;

&lt;p&gt;Pry comes with a number of &lt;a href=&quot;https://github.com/pry/pry/wiki/State-navigation&quot;&gt;helpful commands&lt;/a&gt; for code navigation. An important command is &lt;code class=&quot;highlighter-rouge&quot;&gt;exit&lt;/code&gt;, which will stop the at a specified break point and let the code continue to either the next break point or until completion.&lt;/p&gt;

&lt;p&gt;Multiple &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; lines may be added to different files in order to jump from break point to break point. If we wanted to dig deeper, to see what the &lt;code class=&quot;highlighter-rouge&quot;&gt;accessor&lt;/code&gt; variable is in &lt;code class=&quot;highlighter-rouge&quot;&gt;write_store_attribute&lt;/code&gt;, we could place a second &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# In activerecord-4.2.4/lib/active_record/store.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;accessor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_accessor_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pry&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;accessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, &lt;code class=&quot;highlighter-rouge&quot;&gt;exit&lt;/code&gt; and re-running &lt;code class=&quot;highlighter-rouge&quot;&gt;rails console&lt;/code&gt; shows both break points in action.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;contact_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;phone: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;86&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pry&#39;&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;87&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:contact_method&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;88&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pry&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;89&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;91&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;129&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;130&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;accessor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_accessor_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;131&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pry&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;132&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;accessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;133&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accessor&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; ActiveRecord::Store::StringKeyedHashAccessor&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; def self.write(object, attribute, key, value)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt;   super object, attribute, key.to_s, value&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;More break points, more knowledge. Each new &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt; gives a new context which subsequently opens more avenues of exploration. This is obviously not the end of the &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt; logic, but a great first step has been made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: The &lt;code class=&quot;highlighter-rouge&quot;&gt;@&lt;/code&gt; command can be used to show the current bound context. This is especially helpful if many different debug or output statements have been used in one bind point.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;rinse-and-repeat&quot;&gt;4. Rinse and Repeat&lt;/h2&gt;

&lt;p&gt;Following the same pattern, any depth of code can be reached by placing a &lt;code class=&quot;highlighter-rouge&quot;&gt;binding.pry&lt;/code&gt;, observing results and repeating. Traveling through code that is foreign will also help build confidence. When developers stop assuming that things are black boxes of magic, everyone benefits.&lt;/p&gt;

&lt;p&gt;Using these simple techniques, code previously hidden or otherwise out of reach becomes accessible and easy to traverse. Finally, I would advise to keep trips down the code rabbit hole short, or you might shave &lt;a href=&quot;https://www.hanselman.com/blog/YakShavingDefinedIllGetThatDoneAsSoonAsIShaveThisYak.aspx&quot;&gt;one too many yaks&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Building a Simple Web Server with Ruby 2.0+ (Part 2)</title>
   <link href="https://jakeyesbeck.com/2015/10/18/building-a-simple-web-server-with-ruby-2-part-2/"/>
   <updated>2015-10-18T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/10/18/building-a-simple-web-server-with-ruby-2-part-2</id>
   <content type="html">&lt;p&gt;In &lt;a href=&quot;https://jakeyesbeck.com/2015/10/11/building-a-simple-web-server-with-ruby-2/&quot;&gt;a previous post&lt;/a&gt;, a very simple Ruby server was created to listen to HTTP requests. While great for a first step, this example server does nothing more than respond with “Hello World”. Greetings are nice and polite, but I think we can do better.&lt;/p&gt;

&lt;h2 id=&quot;pro-filing&quot;&gt;Pro-filing&lt;/h2&gt;

&lt;p&gt;A reasonable feature for this simple server is the ability to serve files. When retrieving files, the server must remain secure, only serving files that should be readable by clients. Additionally, if a requested file does not exist, the server should make the client aware.&lt;/p&gt;

&lt;p&gt;Since a request can have multiple parts, the server will need to parse out the noise from the desired file. For instance, if the request looks like &lt;code class=&quot;highlighter-rouge&quot;&gt;/path/to/my_file.html?query=params&amp;amp;are=cool&lt;/code&gt;, the server should remove all query parameters and search for &lt;code class=&quot;highlighter-rouge&quot;&gt;my_file.html&lt;/code&gt; nested within the &lt;code class=&quot;highlighter-rouge&quot;&gt;/path/to/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;With an incoming request:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET /path/to/my_file.html?query&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;params&amp;amp;are&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cool HTTP/1.1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A simple file fetching method might look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;uri&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;SEVER_ROOT_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/var/www&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Remove query params and HTTP verb, version&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SERVER_ROOT_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Given a request string input (from &lt;code class=&quot;highlighter-rouge&quot;&gt;request.gets&lt;/code&gt; in the existing code), this method returns an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;File&lt;/code&gt; if it can find the requested file or &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; if it does not exist. The &lt;code class=&quot;highlighter-rouge&quot;&gt;SERVER_ROOT_DIR&lt;/code&gt; is used to ensure the file lookup is centralized to where the server expects the files to be.&lt;/p&gt;

&lt;p&gt;Putting it all together, the server can now fetch and return files that exist.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;socket&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;uri&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;SERVER_ROOT_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/var/www&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SERVER_ROOT_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gets&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetch_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 404 Not Found&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;File not found&#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 200 OK&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: text/plain&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Length: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bytesize&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Connection: close&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, a curl request for an invalid file produces a &lt;code class=&quot;highlighter-rouge&quot;&gt;404&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl localhost:8080/bad_file.html -I

HTTP/1.1 404 Not Found
Content-Type: text/plain
Content-Length: 14
Connection: close
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;more-logic-more-problems&quot;&gt;More Logic, More Problems&lt;/h2&gt;

&lt;p&gt;A few problems are immediately evident with this code. One is that any file that exists on the system can be requested. For instance, the file &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/passwd&lt;/code&gt; is a common target for immature web servers to accidentally expose.&lt;/p&gt;

&lt;p&gt;To combat this, the &lt;code class=&quot;highlighter-rouge&quot;&gt;fetch_file&lt;/code&gt; method can throw out all directory movement inducing path parts:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;insecure_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;secure_request_parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insecure_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reject&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;..&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;secure_request_parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SERVER_ROOT_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will change a path from &lt;code class=&quot;highlighter-rouge&quot;&gt;/../../../my/hidden/file&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;/my/hidden/file&lt;/code&gt;, nullifying the attempt to expose private files.&lt;/p&gt;

&lt;h2 id=&quot;speaking-the-same-language&quot;&gt;Speaking the Same Language&lt;/h2&gt;

&lt;p&gt;A second issue with our new and improved tiny web server is in the response type. Currently, all responses indicate that the type of the file returned is &lt;code class=&quot;highlighter-rouge&quot;&gt;text/plain&lt;/code&gt;. Instead, the response type can be extracted from the file returned. To determine a file’s type, a good place to start is by examining the extension.&lt;/p&gt;

&lt;p&gt;For the request &lt;code class=&quot;highlighter-rouge&quot;&gt;/path/to/my_file.html?query=params&amp;amp;are=cool&lt;/code&gt;, the server must be able to identify that the &lt;code class=&quot;highlighter-rouge&quot;&gt;.html&lt;/code&gt; extension maps to the content type &lt;code class=&quot;highlighter-rouge&quot;&gt;text/html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With the addition of a simple mapping method, the server can respond more intelligently:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;content_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;html: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;text/html&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;txt: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;text/plain&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;application/json&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;text/plain&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This method accepts an extension (like &lt;code class=&quot;highlighter-rouge&quot;&gt;.html&lt;/code&gt;) and maps it to a &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Type&lt;/code&gt;. If no mapping can be found, it assumes that the file is in plain text.&lt;/p&gt;

&lt;p&gt;Using some additional &lt;code class=&quot;highlighter-rouge&quot;&gt;File.extname&lt;/code&gt; extraction, using this &lt;code class=&quot;highlighter-rouge&quot;&gt;content_type&lt;/code&gt; method is simple:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;socket&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;uri&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;SERVER_ROOT_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/var/www&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;insecure_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;secure_request_parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insecure_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reject&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;..&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;secure_request_parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SERVER_ROOT_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;content_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;html: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;text/html&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;txt: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;text/plain&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;application/json&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;text/plain&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gets&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetch_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 404 Not Found&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;File not found&#39;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 200 OK&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sym&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Length: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bytesize&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Connection: close&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The important line is:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_to_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sym&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code results in a symbol to pass to &lt;code class=&quot;highlighter-rouge&quot;&gt;content_type&lt;/code&gt; that returns a meaningful content type for the client.&lt;/p&gt;

&lt;p&gt;The results of a request using this new content type parsing are just as expected:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl localhost:8080/path/to/my_file.html -I

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 79
Connection: close
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There it is! The &lt;code class=&quot;highlighter-rouge&quot;&gt;text/html&lt;/code&gt; content type returned correctly by the server when an html file was requested.&lt;/p&gt;

&lt;h2 id=&quot;good-progress-but-far-from-perfect&quot;&gt;Good Progress but Far from Perfect&lt;/h2&gt;

&lt;p&gt;This new iteration has added some good depth to the server; however, a plethora of issues remain. This server still has no concept of thread pooling for memory management, no authentication for restricted access files, and can only fetch basic files.&lt;/p&gt;

&lt;p&gt;While this might be sufficient for a pet project or educational purposes, I must reiterate that using a more mature and maintained web server is preferable.&lt;/p&gt;

&lt;p&gt;It sure has been fun building it though, right?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Building a Simple Web Server with Ruby 2.0+</title>
   <link href="https://jakeyesbeck.com/2015/10/11/building-a-simple-web-server-with-ruby-2/"/>
   <updated>2015-10-11T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/10/11/building-a-simple-web-server-with-ruby-2</id>
   <content type="html">&lt;p&gt;The Ruby language can be utilized for a variety of different purposes. The most popular of these is as a web scripting language. The entry point to these applications, the web server, is not something that is usually built from the ground up. Most applications have the lines &lt;code class=&quot;highlighter-rouge&quot;&gt;gem &#39;puma&#39;&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;gem &#39;unicorn&#39;&lt;/code&gt; in their &lt;code class=&quot;highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;. Those are high quality web servers that were built and are maintained by very talented people, but how do they work?&lt;/p&gt;

&lt;p&gt;The aforementioned web servers are just Ruby gems written by Rubyists. While they are awesome gems, &lt;a href=&quot;https://jakeyesbeck.com/2015/08/16/gems-are-not-magic/&quot;&gt;they are not magic&lt;/a&gt;. A basic web server can be written to satisfy some very simple requests.&lt;/p&gt;

&lt;h2 id=&quot;get-basic&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;GET&lt;/code&gt; Basic&lt;/h2&gt;

&lt;p&gt;The job of a web server is to take an incoming request, decide what it means and respond accordingly. Essentially, we want to read some text, process it, and send some other text as response. To create a very simple server, the built in &lt;code class=&quot;highlighter-rouge&quot;&gt;Socket&lt;/code&gt; library will be utilized.&lt;/p&gt;

&lt;p&gt;The goal of this tiny server will be to listen to &lt;code class=&quot;highlighter-rouge&quot;&gt;localhost&lt;/code&gt; requests on port &lt;code class=&quot;highlighter-rouge&quot;&gt;8080&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;socket&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;hello world&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And there it is! A ridiculously tiny web server written in Ruby. Dissecting this code, we see how simple the &lt;code class=&quot;highlighter-rouge&quot;&gt;Socket&lt;/code&gt; library makes this task.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This line makes a new &lt;code class=&quot;highlighter-rouge&quot;&gt;TCPServer&lt;/code&gt; instance that will accept requests to port &lt;code class=&quot;highlighter-rouge&quot;&gt;8080&lt;/code&gt; and defaults to &lt;code class=&quot;highlighter-rouge&quot;&gt;localhost&lt;/code&gt; as the host. The important method on the &lt;code class=&quot;highlighter-rouge&quot;&gt;TCPServer&lt;/code&gt; instance is &lt;code class=&quot;highlighter-rouge&quot;&gt;accept&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Since this server is meant to respond to any request on port &lt;code class=&quot;highlighter-rouge&quot;&gt;8080&lt;/code&gt;, an infinite loop is created so that more than one request can be fulfilled before the process exits.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;hello world&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here is the real logic of the server. The &lt;code class=&quot;highlighter-rouge&quot;&gt;accept&lt;/code&gt; method returns a new instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;TCPSocket&lt;/code&gt; which can be used to communicate with a client. A response string, &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;hello world&#39;&lt;/code&gt;, is then printed to the client and the connection is closed.&lt;/p&gt;

&lt;p&gt;Saving this code to &lt;code class=&quot;highlighter-rouge&quot;&gt;example_server.rb&lt;/code&gt;, the server can be started with &lt;code class=&quot;highlighter-rouge&quot;&gt;ruby example_server.rb&lt;/code&gt; in a console.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;curl&lt;/code&gt; to test this server results in:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; curl localhost:8080
hello world
curl: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;56&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Recv failure: Connection reset by peer
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Alright, alright, the &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;hello world&#39;&lt;/code&gt; has been printed to the console but it looks like there might be an issue. &lt;code class=&quot;highlighter-rouge&quot;&gt;Connection reset by peer&lt;/code&gt;, what the heck does that mean? It means that the server did not send enough information to the client, particularly about when to close the connection. The client is expecting more data than this very naive server is providing. The client expects header data.&lt;/p&gt;

&lt;h2 id=&quot;look-ma-no-header&quot;&gt;Look Ma, no Head(er)!&lt;/h2&gt;

&lt;p&gt;An HTTP header consists of many colon-separated key-value pairs deliminated by a return and newline combination. Everything from a status code to response size can be returned in an HTTP header.&lt;/p&gt;

&lt;p&gt;For this simple example, a status code, &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Type&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;Connection&lt;/code&gt; will be added to the response header.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;socket&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;hello world&#39;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 200 OK&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: text/plain&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Length: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bytesize&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Connection: close&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With this additional information, a client using this server will know the type, size, and connection status of its request. This will enable the client to respect the content type, parse the result intelligently and close the connection.&lt;/p&gt;

&lt;p&gt;An interesting detail about HTTP headers is the way they end. A single line consisting of a return newline, &lt;code class=&quot;highlighter-rouge&quot;&gt;request.puts &quot;\r\n&quot;&lt;/code&gt;, is how the client knows that the HTTP header is finished.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: If a server like this is created for any real requests, hard-coded response headers is not the best idea&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;heads-up&quot;&gt;Head’s up&lt;/h2&gt;

&lt;p&gt;Now, the same &lt;code class=&quot;highlighter-rouge&quot;&gt;curl localhost:8080&lt;/code&gt; test to the new and improved server returns no error:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; curl localhost:8080
hello world
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The new headers are visible via &lt;code class=&quot;highlighter-rouge&quot;&gt;curl localhost:8080 -I&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; curl localhost:8080 -I
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 11
Connection: close
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The server is now responding in a sensible way, but a problem still exists. If more than one request is made, the first request will be processed and all others will wait.&lt;/p&gt;

&lt;p&gt;This implementation is not adequate for concurrent request handling, but another built in solution is readily available.&lt;/p&gt;

&lt;h2 id=&quot;threads-the-needle&quot;&gt;Threads the Needle&lt;/h2&gt;

&lt;p&gt;An easy way to achieve basic concurrency with this server is via &lt;code class=&quot;highlighter-rouge&quot;&gt;Threads&lt;/code&gt;. Out of the box Ruby uses the Matz’s Ruby Interpreter or MRI. MRI is not capable of true concurrency (due to the Global Interpreter Lock) but built in threads will be just fine for this small server.&lt;/p&gt;

&lt;p&gt;This example can be extended to use threads by wrapping the responsibility of the request in a block:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;socket&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;hello world&#39;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 200 OK&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: text/plain&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Length: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bytesize&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Connection: close&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Voila! A simple threaded Ruby server!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: As with the previous solution, this might not be fit for a production environment since every single request spawns a new thread within a single process&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-now&quot;&gt;What now?&lt;/h2&gt;

&lt;p&gt;Now, this simple server will fulfill concurrent requests in a way that will make sense to its consumers. However, it always responds with &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;hello world&#39;&lt;/code&gt;, regardless of the request data. To fetch and parse the incoming data, &lt;code class=&quot;highlighter-rouge&quot;&gt;request.gets&lt;/code&gt; is available:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;socket&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;hello world&#39;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gets&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# handle request information&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 200 OK&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: text/plain&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Length: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bytesize&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Connection: close&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Other improvements would be header configuration, incoming request parsing, and thread pooling.&lt;/p&gt;

&lt;p&gt;Spending a thousand hours iterating on this code will certainly improve its quality, but it still might not allow this simple server stack up to the leaders in the space. I would recommend using a more battle tested web server for an actual production application. At least some of those awesome servers’ mysteries have been explained.&lt;/p&gt;

&lt;p&gt;To see even more improvements, check out &lt;a href=&quot;https://jakeyesbeck.com/2015/10/18/building-a-simple-web-server-with-ruby-2-part-2/&quot;&gt;part 2!&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Someone Wrote that Code on Purpose</title>
   <link href="https://jakeyesbeck.com/2015/10/04/someone-wrote-that-code-on-purpose/"/>
   <updated>2015-10-04T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/10/04/someone-wrote-that-code-on-purpose</id>
   <content type="html">&lt;p&gt;One of the great misconceptions of software engineering is the belief that &lt;em&gt;“any code written in the past is probably wrong”&lt;/em&gt;. For some reason, an accepted mindset (usually among junior developers) is that older code was written with haste or by someone who did not fully understand the problem at hand, invalidating its existence.&lt;/p&gt;

&lt;p&gt;A multitude of rationalizations may arise when the thought of refactoring software from the ground up is an option. After all, the person who wrote that code may not even be around anymore. They could have just been learning the language, surely that is a valid enough reason to completely decimate their work. What possible justification could there be for the opposite? The code just &lt;strong&gt;feels&lt;/strong&gt; wrong, and I, the new domain expert, will rectify this situation!&lt;/p&gt;

&lt;h2 id=&quot;the-devilish-details&quot;&gt;The Devilish Details&lt;/h2&gt;

&lt;p&gt;A person who stumbles on older code can not possibly have the same level of understanding as its original author. Do not misunderstand, it is completely possible that the original author had an insufficient amount of knowledge when writing the code; however, if details have been lost between code inception and re-discovery, removing that code could have dire consequences. How dire could they be? &lt;a href=&quot;https://www.bloombergview.com/articles/2015-09-30/high-speed-trading-firm-deleted-some-code-by-accident&quot;&gt;Well according to a recent Bloomberg article&lt;/a&gt;, it could be millions of dollars.&lt;/p&gt;

&lt;p&gt;According to the article:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Core Engineering developer did not understand that the changes he made to the code sequences would affect the directed ISOs generated by Latour’s trading algorithms.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The key words to take away here is that the developer literally &lt;strong&gt;did not understand the code&lt;/strong&gt;. The developer that made this mistake needed to simply understand the code that he or she was editing. However, due to time constraints, inexperience, or just plain arrogance, that crucial understanding was never reached. The small yet significant details of how the code worked within itself and with external services were never discovered, leading to a catastrophe.&lt;/p&gt;

&lt;h2 id=&quot;assume-smart-people-wrote-it&quot;&gt;Assume Smart People Wrote It&lt;/h2&gt;

&lt;p&gt;A simple rule that may help avoid multi-million dollar code rewrites is to make the assumption that the person who wrote that older piece of software is smart. With some exception, software currently running a business or application was written with care and planning. Time may have passed and the form or shape of the code might not be modern, but in those misplaced curves and edges might lurk the solution to some rarely seen and deadly problems.&lt;/p&gt;

&lt;p&gt;In very lucky situations, the older software might be written by a current employee. This makes that person the obvious best candidate to ask about why the code might &lt;em&gt;“look weird”&lt;/em&gt; or &lt;em&gt;“does this obviously wonky thing”&lt;/em&gt;. Asking this person about the code or tagging them in the inevitable pull request might just save a few production meltdowns.&lt;/p&gt;

&lt;h2 id=&quot;take-a-break-and-re-visit&quot;&gt;Take a Break and Re-visit&lt;/h2&gt;

&lt;p&gt;If no resources are present and a full code obliteration seems like the right approach, it would be wise to walk away and think for a short amount of time. Thinking about a rewrite in a relaxed environment could help make sure no bit is left unturned. Remember, the code in question was most likely reviewed, iterated on, and deliberately turned into its current state.&lt;/p&gt;

&lt;p&gt;If solo breaks do not help get the cognitive juices flowing, try explaining the software design and purpose to an ever attentive &lt;a href=&quot;https://en.wikipedia.org/wiki/Rubber_duck_debugging&quot;&gt;Rubber Duck&lt;/a&gt;. Quackers might not offer the best repartee, but speaking about the code aloud might shine some light onto the darker bytes.&lt;/p&gt;

&lt;h2 id=&quot;learn-and-burn&quot;&gt;Learn and Burn&lt;/h2&gt;

&lt;p&gt;Finally, if the code has been understood and its existence is not longer required, feel free to unleash napalm and build elegant skyscrapers on top of the ruins. Because sometimes, and hopefully only sometimes, that old software hiding under a mountain of neglect really is in need of a phoenix-style rebirth. It is possible that it was written by that intern who only got the job because they were the son or daughter of the CEO’s neighbor. Maybe it was code written by an independent contractor who thought it would be funny to name their variables after famous superheros. Whatever the case may be, stopping to make very deliberate changes will pay dividends.&lt;/p&gt;

&lt;p&gt;Taking time to understand old or opaque code can mean the difference between a healthy face lift to an application and accidentally removing its liver. How are you supposed to have a celebratory drink after a grand refactoring without a liver?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Create a Custom Enumerable</title>
   <link href="https://jakeyesbeck.com/2015/09/27/how-to-create-a-custom-enumerable/"/>
   <updated>2015-09-27T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/09/27/how-to-create-a-custom-enumerable</id>
   <content type="html">&lt;p&gt;Ruby is a wonderfully flexible language. An example of this flexibility is in the ability to define a custom collection class that acts as an &lt;a href=&quot;https://ruby-doc.org/core-2.1.1/Enumerable.html&quot;&gt;Enumerable&lt;/a&gt; object. In Ruby, a collection that acts as an &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; is basically a class which holds a list of objects and exposes helpful methods for iteration and collection. An example of this pattern built into Ruby is the &lt;a href=&quot;https://ruby-doc.org/core-2.2.3/Array.html&quot;&gt;Array&lt;/a&gt; class.&lt;/p&gt;

&lt;p&gt;In keeping with a &lt;a href=&quot;https://jakeyesbeck.com/2015/09/13/rescue-groups/&quot;&gt;theme&lt;/a&gt;, let us assume that an application about dogs exists. In this example, a &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; class exists that will hold information about each dog in the kennel and detailed information about said kennel. We can also assume that this class is meant to be used as a collection of dogs, exposing helper methods for information about the kennel. Why would we use this collection class over a typical &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt;? One reason might be that the consumer of this class expects a list of dogs and some additional metadata. That metadata can be easily exposed in this class without having to wrap the class or extract the metadata from an included &lt;code class=&quot;highlighter-rouge&quot;&gt;Hash&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DogKennel&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:operating_hours&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operating_hours&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@dogs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dogs&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@operating_hours&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operating_hours&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;add-include-enumerable&quot;&gt;1. Add &lt;code class=&quot;highlighter-rouge&quot;&gt;include Enumerable&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;To make our &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; into something that can iterate over its dogs easily, we can add the &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; module. The desired functionality will have iterative functions as instance methods, so &lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; will be used:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DogKennel&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Enumerable&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:operating_hours&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operating_hours&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@dogs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dogs&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@operating_hours&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operating_hours&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This &lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; will allow the &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; class to inherit a large number of useful methods; however, none of these methods are able to be used until a basic iterative &lt;code class=&quot;highlighter-rouge&quot;&gt;each&lt;/code&gt; method is defined. If a method such as &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt; is called in this state, the &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; class will throw a &lt;code class=&quot;highlighter-rouge&quot;&gt;NoMethodError&lt;/code&gt; until the &lt;code class=&quot;highlighter-rouge&quot;&gt;each&lt;/code&gt; method is defined.&lt;/p&gt;

&lt;h2 id=&quot;define-an-each-method&quot;&gt;2. Define an &lt;code class=&quot;highlighter-rouge&quot;&gt;each&lt;/code&gt; Method&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;each&lt;/code&gt; method is the building block for all other iterative methods the &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; module includes. For this example, we can assume that the consumer of &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; will want to iterate over the dogs in the kennel. The &lt;code class=&quot;highlighter-rouge&quot;&gt;each&lt;/code&gt; method must accept a block and either yield or pass the block along to another method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DogKennel&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Enumerable&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@dogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Hooray! Now, the &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; class can respond to &lt;code class=&quot;highlighter-rouge&quot;&gt;each&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;select&lt;/code&gt; and all the other documented &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; iterative methods.&lt;/p&gt;

&lt;p&gt;Some examples of how this class can now be used:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dog_kennel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DogKennel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Fido&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Spot&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Bandit&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Tallahassee&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;09:00 - 18:00&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog_kennel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is here!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Fido is here!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Spot is here!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Bandit is here!&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog_kennel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&#39;Fido&#39;, &#39;Spot&#39;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As always, this is not the only way to achieve this solution in Ruby. Ruby-ists are blessed with a plethora of tools to do any task. I am of the opinion that for this specific task, making a custom collection class is clean and concise. Delegation might be an attractive option but could prove to be overly verbose for this use case.&lt;/p&gt;

&lt;h2 id=&quot;consider-comparisons&quot;&gt;3. Consider Comparisons&lt;/h2&gt;

&lt;p&gt;In this new collection class, the &lt;code class=&quot;highlighter-rouge&quot;&gt;sort&lt;/code&gt; method will default using the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; (sometimes called spaceship) operator. This combined comparison operator returns &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt; if first operand equals the second, &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt; if first operand is greater than the second and &lt;code class=&quot;highlighter-rouge&quot;&gt;-1&lt;/code&gt; if first operand is less than the second.&lt;/p&gt;

&lt;p&gt;This will work fine for strings and other basic object types; however, if a more complex object held the information about each dog, the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; method must be defined on that object.&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class is created to represent a dog’s attributes:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:breed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:color&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;breed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@breed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;breed&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then, instances of &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; are then given to &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; on initialization and sorted:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fido&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Daschund&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Fido&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;brown&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bandit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Labrador&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Bandit&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;black&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog_kennel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DogKennel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fido&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bandit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Tallahassee&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;09:00 - 18:00&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog_kennel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; ArgumentError: comparison of Dog with Dog failed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This error is to be expected since the &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class has no way to compare one instance of itself against another. To maintain feature parity with the first example, we can define the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; method that introspects on each &lt;code class=&quot;highlighter-rouge&quot;&gt;Dog&lt;/code&gt;’s name:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other_dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, we can sort those puppies!&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dog_kennel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [#&amp;lt;Dog:0x007fcb4a01c800 @name=&quot;Bandit&quot;, @breed=&quot;Labrador&quot;, @color=&quot;black&quot;&amp;gt;,&lt;/span&gt;
     &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Dog:0x007fcb4914b880 @name=&quot;Fido&quot;, @breed=&quot;Daschund&quot;, @color=&quot;brown&quot;&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;its-raining-iterators-and-dogs&quot;&gt;It’s Raining Iterators and Dogs&lt;/h2&gt;

&lt;p&gt;Having the &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; module included and the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;=&amp;gt;&lt;/code&gt; comparison operator defined, the &lt;code class=&quot;highlighter-rouge&quot;&gt;DogKennel&lt;/code&gt; class can now be used in the same convenient way as other collection classes.&lt;/p&gt;

&lt;p&gt;The strength behind this approach is expressed through its maintainability. Since no long list of methods was defined, and no duplicative code was written, this code can exist alongside active development of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; module. For the example in question, this could be an overkill solution. But, in a more complex and sophistiacted system, using the &lt;code class=&quot;highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; could be the best option.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Just learn Rails (Part 3) HTTP status codes</title>
   <link href="https://jakeyesbeck.com/2015/09/20/rails-http-status-codes/"/>
   <updated>2015-09-20T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/09/20/rails-http-status-codes</id>
   <content type="html">&lt;p&gt;So you want to be a Rails superstar? To live large, big servers, requesting tars. Writing code all over the world, gotta make commits constantly. Great, I feel the same way.&lt;/p&gt;

&lt;p&gt;Assuming you have already had that &lt;em&gt;“I should &lt;a href=&quot;https://jakeyesbeck.com/2015/05/17/just-learn-rails/&quot;&gt;just learn Rails&lt;/a&gt;”&lt;/em&gt; moment, the idea of writing an API for a super awesome application might be on the horizon. And, of course, the framework that makes the most sense is Ruby on Rails. Given that is the direction things might naturally evolve, creating an API with Rails can gloss over a few crucial design concepts and considerations.&lt;/p&gt;

&lt;h2 id=&quot;http-status-codes-are-important&quot;&gt;HTTP status codes are important&lt;/h2&gt;

&lt;p&gt;When the &lt;strong&gt;Hypertext Transfer Protocol&lt;/strong&gt; (or HTTP) was conceived, the idea of a server responding with multiple distinct pieces of data came into existence. Officially, HTTP is a stateless application-level protocol for distributed, collaborative, hypertext information system. In other words, it is a standard way that one server can talk to another in a predefined fashion. This is especially useful when writing a system that will facilitate requests from someone other than the person which built it; e.g. an HTTP API.&lt;/p&gt;

&lt;p&gt;The aspect of HTTP that is most relevant in this post are &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes&quot;&gt;status codes&lt;/a&gt;. These codes explicitly tell consumers of an application how they should react to a request. From authorization issues to an incorrect arity of parameters, a large amount of information is exposed via HTTP status codes.&lt;/p&gt;

&lt;h2 id=&quot;rails-status-code-support&quot;&gt;Rails status code support&lt;/h2&gt;

&lt;p&gt;Let us assume that an application exists to look up information about books. To get a specific book, a RESTful route is provided by the application at &lt;code class=&quot;highlighter-rouge&quot;&gt;https://mycoolbookapp.com/books/12&lt;/code&gt;. This route might execute the following controller action:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BooksController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This simple controller action can respond with three HTTP status codes. A &lt;code class=&quot;highlighter-rouge&quot;&gt;200&lt;/code&gt; will be in the response of any &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; which matches the &lt;code class=&quot;highlighter-rouge&quot;&gt;:id&lt;/code&gt; supplied. Likewise, a &lt;code class=&quot;highlighter-rouge&quot;&gt;404&lt;/code&gt; will automatically be returned if the &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt; requested does not exist. Finally, if some “code in need of improvement” is accessed and fails, a &lt;code class=&quot;highlighter-rouge&quot;&gt;500&lt;/code&gt; is returned to let the user know that the server has almost certainly caught fire &lt;em&gt;(surely no code pushed to production has bugs in it)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For a very simple API, this response structure is adequate. However, achieving more complicated responses might not be so straight forward. For instance, if a user must be logged in to access a &lt;code class=&quot;highlighter-rouge&quot;&gt;Book&lt;/code&gt;, the correct response might be &lt;code class=&quot;highlighter-rouge&quot;&gt;401&lt;/code&gt;, to explicitly let the user know that they are not authorized to see that resource.&lt;/p&gt;

&lt;p&gt;If HTTP status codes are unknown or underutilized, an inexperienced developer might write that response that attempts to only use the text body of a response.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BooksController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_filter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:authenticate_user&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;error: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;User is not logged in&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code will respond with a &lt;code class=&quot;highlighter-rouge&quot;&gt;200&lt;/code&gt; and a message denoting an error. This is not the correct way to return a result. This is the equivalent of someone allowing you to leave a store with an item and not pay, then arresting you for it. It just does not make sense and should be avoided.&lt;/p&gt;

&lt;p&gt;Instead, Ruby on Rails gives us &lt;a href=&quot;https://billpatrianakos.me/blog/2013/10/13/list-of-rails-status-code-symbols/&quot;&gt;very helpful symbols&lt;/a&gt; that can be used to accurately convey the appropriate response to end users.&lt;/p&gt;

&lt;p&gt;To only return the correct HTTP status code, the books controller can be rewritten to:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BooksController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_filter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:authenticate_user&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unauthorized&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Additionally, you can provide even more information to the consumer of your API with a combination of HTTP status codes and a response body:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BooksController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_filter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:authenticate_user&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;error: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;User is not logged in&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unauthorized&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:ok&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;json: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;communicate-effectively&quot;&gt;Communicate effectively&lt;/h2&gt;

&lt;p&gt;This example has exposed the difference between a decent API and one that understands how HTTP should work. While the specific problem &lt;a href=&quot;https://github.com/CanCanCommunity/cancancan&quot;&gt;could be solved with CanCanCan&lt;/a&gt;, it is important to understand how and why those libraries work the way that they do.&lt;/p&gt;

&lt;p&gt;If one were to continue down the naive path, returning hashes or strings with incorrect HTTP status codes, things would become messy quickly. That response structure unjustly handcuffs the API clients to be unnecessarily tolerant of ad-hoc text responses. But, if the API conforms to HTTP standards, a client knows exactly what each response means. A &lt;code class=&quot;highlighter-rouge&quot;&gt;400&lt;/code&gt; status code in the response will give context to what a supplied error means. The client can respond correctly and know that their request resulted in an error. However, if a response body is the only way to denote that something went wrong, what stops a new developer on the API from changing the &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt; key to &lt;code class=&quot;highlighter-rouge&quot;&gt;Error&lt;/code&gt; and ruin everyone’s day?&lt;/p&gt;

&lt;p&gt;Instead of capturing in text every single detail about why a request did not result in an expected response, use HTTP status codes to supplement and communicate effectively.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rescue Groups Ruby Wrapper</title>
   <link href="https://jakeyesbeck.com/2015/09/13/rescue-groups/"/>
   <updated>2015-09-13T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/09/13/rescue-groups</id>
   <content type="html">&lt;p&gt;People need companions. We are a social species that enjoys surrounding itself with family and friends. But sometimes, and maybe more often than just sometimes, people crave companionship from something that cannot talk back. This is probably one of the reasons so many people like pets. A pet cannot disagree with you or say judgmental remarks as you fill up that wine glass for a fourth time. No, a good pet will simply exist near you, occasionally asking for pets and food. Pets can be obtained from breeders for huge stacks of cash, or they can be adopted for significantly cheaper.&lt;/p&gt;

&lt;h2 id=&quot;the-adoption-option&quot;&gt;The Adoption Option&lt;/h2&gt;

&lt;p&gt;About 2.7 million animals are euthanized each year in animal shelters across the United States. That is some sad stuff right there. These animals could be hanging out with you at your house, clawing up the couch or barking at nothing. Does that not sound like just the best time? If only there was a Ruby library that some super awesome Software Artisans could use to make discoverable pet data a reality. Well now, there is! Over the past few months, as part of the &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt; initiative, I have built a &lt;a href=&quot;https://github.com/yez/rescue_groups&quot;&gt;wrapper for the RescueGroups.org API&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;sign-up-for-an-api-key&quot;&gt;0. Sign up for an API key&lt;/h2&gt;

&lt;p&gt;The RescueGroups API is free to use, but requires signing up for an API key. To do that, fill out &lt;a href=&quot;https://www.rescuegroups.org/services/request-an-api-key/&quot;&gt;this form&lt;/a&gt; and they will email you an API key for you to use.&lt;/p&gt;

&lt;h2 id=&quot;install-the-rescuegroups-gem&quot;&gt;1. Install the &lt;code class=&quot;highlighter-rouge&quot;&gt;rescue_groups&lt;/code&gt; Gem&lt;/h2&gt;

&lt;p&gt;To install the gem, simply add &lt;code class=&quot;highlighter-rouge&quot;&gt;rescue_groups&lt;/code&gt; to a ruby project’s Gemfile:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemfile&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rubygems&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rescue_groups&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then in an initializer or at the beginning of the execution flow for using the library, add your new fancy API key to the configuration.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;RescueGroups&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;apikey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;your api key&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;use-the-gem&quot;&gt;2. Use the Gem!&lt;/h2&gt;

&lt;p&gt;After the gem is installed, some handy dandy search functionality is right at your fingertips. Call me biased but I rather like the ActiveRecord &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;where&lt;/code&gt; API. In fact, I like it so much that the &lt;code class=&quot;highlighter-rouge&quot;&gt;rescue_groups&lt;/code&gt; gem implemented its own version of both.&lt;/p&gt;

&lt;h3 id=&quot;searching&quot;&gt;Searching&lt;/h3&gt;

&lt;p&gt;If an ID is known for an animal, simply pass it to &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; and it will return an &lt;code class=&quot;highlighter-rouge&quot;&gt;Animal&lt;/code&gt; object. If an &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt; is given to &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt;, it will return an &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt; of &lt;code class=&quot;highlighter-rouge&quot;&gt;Animal&lt;/code&gt;s.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &amp;lt;Animal id: 1, name: &#39;Fluffy&#39; ...&amp;gt;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&amp;lt;Animal id: 20, name: &#39;Mittens&#39; ...&amp;gt;, &amp;lt;Animal id: 30, name: &#39;Mr. Doom&#39; ...&amp;gt;, &amp;lt;Animal id: 40, name: &#39;CatDog&#39; ...&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Where&lt;/code&gt; is very similar, any of the supported fields for &lt;a href=&quot;https://github.com/yez/rescue_groups/blob/master/docs/animal_field.md&quot;&gt;Animals&lt;/a&gt;, &lt;a href=&quot;https://github.com/yez/rescue_groups/blob/master/docs/organization_field.md&quot;&gt;Organizations&lt;/a&gt;, and &lt;a href=&quot;https://github.com/yez/rescue_groups/blob/master/docs/event_field.md&quot;&gt;Events&lt;/a&gt; can be used to find the matching records.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Pets-R-Us&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [&amp;lt;Organization id: 1, name: &#39;Pets-R-Us&#39; ...&amp;gt;]&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;color: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;black&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;brown&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [&amp;lt;Animal id: 1, color: &#39;black&#39; ..&amp;gt;, &amp;lt;Animal id: 5, color: &#39;brown&#39; ..&amp;gt;]&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;location_postal_code: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;94117&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The default behavior asserts that the fields are equal, i.e. An animal that is brown will be returned when &lt;code class=&quot;highlighter-rouge&quot;&gt;Animal.where(color: &#39;brown&#39;)&lt;/code&gt; is used. Other comparisons are possible for more complex queries.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;general_age: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;less_than: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [&amp;lt;Animal id: 1, age: 2 ..&amp;gt;, &amp;lt;Animal id: 3, age: 1 ..&amp;gt;]&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;contains: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;shelter&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;location: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90210&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [&amp;lt;Organization id: 1, name: &#39;Big Animal Shelter&#39;, location: 90210 ...&amp;gt;, &amp;lt;Organization id: 2, name: &#39;Small Animal Shelter&#39;, location: 90210 ...&amp;gt;,]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;relationships&quot;&gt;Relationships&lt;/h2&gt;

&lt;p&gt;While I was in the spirit of borrowing, I did so with Ruby on Rails style relationships. In the &lt;code class=&quot;highlighter-rouge&quot;&gt;rescue_groups&lt;/code&gt; gem Animals and Events &lt;code class=&quot;highlighter-rouge&quot;&gt;belongs_to&lt;/code&gt; Organizations and, inversely, Organizations &lt;code class=&quot;highlighter-rouge&quot;&gt;has_many&lt;/code&gt; Animals and Events. When one of these models’ relationship is called, the respective relationship is automagically fetched from the RescueGroups.org API.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;organization&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;lt;Organization id: 1, name: &#39;Pets&#39;, city: &#39;Dallas&#39; ...&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# This will issue a remote call that is equivalent to Animal.where(organization_id: 1)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;animals&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [&amp;lt;Animal id: 1, organization_id: 1 ...&amp;gt;, &amp;lt;Animal id: 2, organization_id: 1 ...&amp;gt;, ...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;make-a-pet-project&quot;&gt;3. Make a Pet Project&lt;/h2&gt;

&lt;p&gt;Now with all this pet data available, put it to work. I have really enjoyed making this library but am always looking for feedback. If anyone would like to know more or help contribute to this project please feel free! Github PRs and issues are always welcome.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Stop and Take a Moment</title>
   <link href="https://jakeyesbeck.com/2015/09/06/stop-and-take-a-moment/"/>
   <updated>2015-09-06T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/09/06/stop-and-take-a-moment</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/images/chris-bell-bench.jpg&quot; alt=&quot;Chris Bell&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Someone in all our lives has offered up the advice: “Slow down”. It might have happened once or, if we are lucky, many people have said it. Regardless, the words did not sink in. At least not at first. And even to this day, maybe the words are yet to truly be absorbed and understood. But those words do not mean anything, it is just something people say, right? Wrong. These little words carry more weight with them than most conversations in a day.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I am just too busy”&lt;/em&gt;, &lt;em&gt;“There is no time to waste, how could I slow down?”&lt;/em&gt;, we say in response. Because in the moment, these phrases make sense. Things that are right in front of our face are the most important. We may plan slightly in the future or be cognizant of a few days in the past, but we stay busy. After all, being busy has become our natural and most comfortable state.&lt;/p&gt;

&lt;h2 id=&quot;busyness-is-mindlessness&quot;&gt;Busyness is mindlessness&lt;/h2&gt;

&lt;p&gt;In an earlier post, I said &lt;a href=&quot;https://jakeyesbeck.com/2015/06/28/staying-motivated/&quot;&gt;to keep moving, to keep working&lt;/a&gt;. The message of this article is not in contradiction to that one, but should be thought of as complementary. Staying still will cause fatigue, muscle atrophy, and many other problems; but, not enjoying the moments we are in can be just as detrimental. Within this world full of stimuli, it is extremely easy to preoccupy ourselves with just about anything. Think about yesterday or the day before, how many tasks or activities flowed into each other? How long did the entire day feel? For me, days do not feel nearly as long as they used to. Moments flow from one to another without even being noticed. It almost feels like a trance, a mindless sea of moments washing over each other.&lt;/p&gt;

&lt;p&gt;People like to stay busy, to feel valuable and like they have a place in the world. However, this mentality can lead a person to miss out on those special moments that deserve a bit more attention.&lt;/p&gt;

&lt;h2 id=&quot;one-moment-can-mean-a-lifetime&quot;&gt;One moment can mean a lifetime&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;“You don’t know what you’ve got until its gone”&lt;/strong&gt; is a phrase said a great deal, but not often heard. This concept has recently rang very true for me. Memories that seemed so small and insignificant suddenly have a great deal of meaning. It might have been a 5 minute conversation or a multiple day excursion. Either way, the memories that we have and the moments that we use to define ourselves are happening to us every single day. It is important that they are noticed and appreciated.&lt;/p&gt;

&lt;p&gt;In times of sadness, reflection is effortless. It is unfortunate that these feelings are most often surfaced due to despondency, but it can serve as a valuable lesson. A lesson to stop and take a moment to appreciate where we are and who is among us.&lt;/p&gt;

&lt;h2 id=&quot;gone-but-never-forgotten&quot;&gt;Gone but never forgotten&lt;/h2&gt;

&lt;p&gt;I have lost a friend. Truly, I have a lost a brother. While the same blood did not run through our veins, our experiences and connection made us family. I am lucky to have such fond memories and character defining interactions, but I wish that I had taken more time. More time to understand, to appreciate, and to be in the moment when times were at their best. I believe that we are who we are not only by our own volition, but also the influence and teachings of those around us. Some of those teachers we recognize right away, others are taken for granted.&lt;/p&gt;

&lt;p&gt;I wish that I had said how much I valued our time together, how much I have learned and what you really meant to me. I would not be who I am today without you. I regret never telling you in person, but feel blessed that I have as many fond memories as I do.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dedicated to Christopher Adam Bell&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Active Support and Time</title>
   <link href="https://jakeyesbeck.com/2015/08/30/active-support-and-time/"/>
   <updated>2015-08-30T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/08/30/active-support-and-time</id>
   <content type="html">&lt;p&gt;If a list was compiled of useful Ruby libraries, Active Support would be close to the top. Based on the &lt;a href=&quot;https://api.rubyonrails.org/classes/ActiveSupport.html&quot;&gt;documentation alone&lt;/a&gt;, it is apparent that a very large amount of time went into thinking about the roles Active Support should play and the functionality it should support. From string manipulation to internationalization, Active Support seems to simply do it all. However, even a profoundly useful library like Active Support still has a few inconsistencies with everyone’s favorite subject: &lt;strong&gt;Time Calculation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;time-wounds-all-heals&quot;&gt;Time wounds all heals&lt;/h2&gt;

&lt;p&gt;Personally, the thing that keeps me up at night, the monster in my closet, the beast waiting to grab my foot when I accidentally let it hang over the bed while sleeping, is time calculation in programming. Regardless of the task, however simple it may seem, calculating time offsets or time zone correction continues to be a tremendous pain point. Now, to demonstrate just how crazy things can be, let’s pick on Active Support.&lt;/p&gt;

&lt;p&gt;Active Support grants a myriad of methods for even the most impatient Software Artisan. For example, if one were to ask for this instant in time, a day ago, Active Support makes it possible.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ago&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2015-08-29 18:44:55 -0700&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Likewise, basic date addition and subtraction is just as easy.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;three_days_from_now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;days&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 2015-09-01 18:46:34 -0700&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;three_days_from_now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hours&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2015-09-03 06:48:28 -0700&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Great! Very simple, seemingly arbitrary time calculation has never been easier. So what could be the catch? Obviously there isn’t one, if there were then this article would have to continue and I’m sure everyone has had quite enough.&lt;/p&gt;

&lt;h2 id=&quot;toi-is-not-always-easy&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;to_i&lt;/code&gt; is not always easy&lt;/h2&gt;

&lt;p&gt;Had enough? Too bad. The topic of &lt;code class=&quot;highlighter-rouge&quot;&gt;to_i&lt;/code&gt; still has to be discussed with relation to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; class. Ruby’s &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; class exposes a method &lt;code class=&quot;highlighter-rouge&quot;&gt;to_i&lt;/code&gt; which can be used to convert a &lt;code class=&quot;highlighter-rouge&quot;&gt;Time&lt;/code&gt; to an &lt;code class=&quot;highlighter-rouge&quot;&gt;Integer&lt;/code&gt;. This &lt;code class=&quot;highlighter-rouge&quot;&gt;Integer&lt;/code&gt;is the sum of seconds passed since &lt;a href=&quot;https://en.wikipedia.org/wiki/Unix_time&quot;&gt;Epoch&lt;/a&gt;. Using Epoch time can be useful for some systems that want to avoid doing timezone conversion. In fact, it might be so attractive an option that a developer’s first instinct might be to save and calculate everything in Epoch time. However, this might not always be the best idea.&lt;/p&gt;

&lt;p&gt;Active Support follows suit with allowing &lt;code class=&quot;highlighter-rouge&quot;&gt;to_i&lt;/code&gt; to be called on its convenience methods. For example, &lt;code class=&quot;highlighter-rouge&quot;&gt;1.day.to_i&lt;/code&gt; calculates the number of seconds in the day.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 86400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And &lt;code class=&quot;highlighter-rouge&quot;&gt;1.week.to_i&lt;/code&gt; calculates the number of seconds in a week.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;week&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 604800&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Additionally, &lt;code class=&quot;highlighter-rouge&quot;&gt;1.month.to_i&lt;/code&gt; calculates the number of seconds in a month.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2592000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Wait a second, that only accounts for 30 days. If I learned anything in kindergarten, it was that the teacher really hates it when you teach yourself to whistle during nap-time. Also, I am pretty sure that not all months consist of exactly 30 days.&lt;/p&gt;

&lt;h2 id=&quot;bad-times&quot;&gt;Bad times&lt;/h2&gt;

&lt;p&gt;Introducing this inconsistency in time calculation can lead to unintended results. For example, note the difference between subtracting time objects and subtracting &lt;code class=&quot;highlighter-rouge&quot;&gt;to_i&lt;/code&gt; calculated times:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;months&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2015-05-30 19:07:44 -0700&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;months&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2015-06-01 19:07:59 -0700&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So which is it Ruby? Was 3 months ago the 1st of June or the 30th of May? The problem persists even if everything is converted to integers first:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;epoch_now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1440986921&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;epoch_three_months_ago&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoc_now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;months&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1433210921&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch_three_months_ago&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2015-06-01 19:08:41 -0700&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;ok-but-why&quot;&gt;Ok, but why?&lt;/h2&gt;

&lt;p&gt;So why does this happen? Why does &lt;code class=&quot;highlighter-rouge&quot;&gt;1.month&lt;/code&gt; return the same integer regardless of which month it is. Because, how could it know? A month is not meant to exist as an abstract concept, there is no canonical “month”, they are either 30 days, 31 days, 28 days, or 29 days long &lt;em&gt;(I didn’t forget about you, leap year!)&lt;/em&gt;. This is just a small demonstration of why time calculation is never as simple as it may seem. There is no silver bullet to avoid it all. Even Epoch time conversions can lead to some real bad times.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>I, Object!</title>
   <link href="https://jakeyesbeck.com/2015/08/23/ruby-objects/"/>
   <updated>2015-08-23T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/08/23/ruby-objects</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;I am lucky enough to work with wonderfully talented people every single day. This is a guest post by one of my magnificent coworkers, &lt;a href=&quot;https://github.com/kristjan&quot;&gt;Kristján Pétursson&lt;/a&gt;. Thank you for allowing me to share this knowledge with everyone!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This post is adapted from my answer to &lt;a href=&quot;https://stackoverflow.com/q/31775576/802618&quot;&gt;this Stack Overflow question&lt;/a&gt;. If you want to start from the beginning of the universe and build out, go read that one. If you prefer to start with something you can touch and work backwards, here we go.&lt;/p&gt;

&lt;p&gt;Ruby likes ducks. Which is to say that when we’re coding, and we have an object, we don’t particularly care what kind of object it is, so long as it responds to the messages we send it. It might be a &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt; or a &lt;code class=&quot;highlighter-rouge&quot;&gt;Child&lt;/code&gt; or a &lt;code class=&quot;highlighter-rouge&quot;&gt;Doctor&lt;/code&gt;, and as long as when we call &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; we hear a noise, all is well. That’s called &lt;a href=&quot;https://en.wikipedia.org/wiki/Duck_typing&quot;&gt;Duck Typing&lt;/a&gt;, and Ruby digs it.&lt;/p&gt;

&lt;p&gt;So if we have some arbitrary object and we ask it to &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt;, the Ruby interpreter needs to figure out where the object’s &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; method is. Nothing’s been compiled, and Ruby lets you define methods pretty much any place or time you like, so &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; needs to be looked up at runtime. That’s called &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic_dispatch&quot;&gt;Dynamic dispatch&lt;/a&gt;, and it’s how Ruby handles ducks.&lt;/p&gt;

&lt;h3 id=&quot;now-for-the-thing-we-can-touch-lets-make-a-duck&quot;&gt;Now for the thing we can touch; let’s make a &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Duck&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;quack&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Quack, I say!&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quack&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Quack, I say!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Surely, this is no surprise. You’ve done this in the past, or quieter things like it, and you understand just fine that a method called on &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt; will be found in &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt;. But we less frequently do things like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quack&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;I&#39;m tired of quacking.&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quack&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; I&#39;m tired of quacking.&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;other_duck&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;other_duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quack&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; Quack, I say!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Hm, so if we can just redefine &lt;code class=&quot;highlighter-rouge&quot;&gt;duck.quack&lt;/code&gt; without messing up &lt;code class=&quot;highlighter-rouge&quot;&gt;other_duck&lt;/code&gt;, where is the second &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; method? It turns out every object has a Singleton Class where it can stash all its personal possessions. Other words for singleton class include metaclass, eigenclass, and virtual class, but Ruby implements a method called &lt;code class=&quot;highlighter-rouge&quot;&gt;#singleton_class&lt;/code&gt;, so we’ll use that one. You can see &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; on &lt;code class=&quot;highlighter-rouge&quot;&gt;duck.singleton_class&lt;/code&gt;, but not on &lt;code class=&quot;highlighter-rouge&quot;&gt;other_duck.singleton_class&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [:quack]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; []&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And then you can see the original &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; on &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt; where we left it:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [:quack]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;drawing-it-out&quot;&gt;Drawing it out&lt;/h3&gt;

&lt;p&gt;Now we can start drawing diagrams, which is great, because people like diagrams almost as much as Ruby likes ducks. When we ask &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt;, it starts looking for the method on &lt;code class=&quot;highlighter-rouge&quot;&gt;duck.singleton_class&lt;/code&gt; and then works its way up until it finds it.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;             +----------+
             | Duck     |
             |   #quack |
             +----------+
                  ^
                  |
                  +-------------------------------------+
                  |                                     |
           +---------------+                    +---------------+
duck ~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |   other_duck ~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |
           |   #quack      |                    +---------------+
           +---------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I’m using &lt;code class=&quot;highlighter-rouge&quot;&gt;~~~&amp;gt;&lt;/code&gt; to move from objects to their singleton class, and then &lt;code class=&quot;highlighter-rouge&quot;&gt;---&amp;gt;&lt;/code&gt;  to move from classes to their superclass.&lt;/p&gt;

&lt;p&gt;And indeed, &lt;code class=&quot;highlighter-rouge&quot;&gt;duck.singleton_class.superclass == Duck&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;#&amp;lt;Class:Duck&amp;gt;&lt;/code&gt; singleton class is an anonymous class brought into existence just for &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;other_duck&lt;/code&gt; has its own singleton class that doesn’t have &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; defined on it, so it traverses upwards and finds &lt;code class=&quot;highlighter-rouge&quot;&gt;#quack&lt;/code&gt; on &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;We can see the whole lookup path with &lt;code class=&quot;highlighter-rouge&quot;&gt;#ancestors&lt;/code&gt;, and can check exactly where a method is defined with &lt;code class=&quot;highlighter-rouge&quot;&gt;#method&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;#ancestors&lt;/code&gt; includes the singleton class as its first entry because that’s the first place we look for a method.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ancestors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [#&amp;lt;Class:#&amp;lt;Duck:0x007fe793031dd0&amp;gt;&amp;gt;, Duck, Object, Kernel, BasicObject]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:quack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; #&amp;lt;Method: #&amp;lt;Duck:0x007fe793031dd0&amp;gt;.quack&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:quack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; #&amp;lt;Method: Duck#quack&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There are more things in &lt;code class=&quot;highlighter-rouge&quot;&gt;#ancestors&lt;/code&gt; than we’ve drawn yet, though I bet you saw them coming. Moving up from &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt;, we get to &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;. Everything in Ruby is an &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;. No, everything. Yes, everything, even &lt;code class=&quot;highlighter-rouge&quot;&gt;BasicObject&lt;/code&gt;, which is an ancestor of &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt; - just go with that for a second. Maybe pretend there was time travel involved.&lt;/p&gt;

&lt;p&gt;When you &lt;code class=&quot;highlighter-rouge&quot;&gt;class Duck&lt;/code&gt;, there’s an implicit &lt;code class=&quot;highlighter-rouge&quot;&gt;class Duck &amp;lt; Object&lt;/code&gt; so your class can inherit everything &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt; has and be a good citizen. The &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;s we were using earlier to look at &lt;code class=&quot;highlighter-rouge&quot;&gt;instance_methods&lt;/code&gt; lets us look only at the methods that class is defining, rather than everything it has inherited, but in reality:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;public_methods&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [:quack, :nil?, :===, :=~, :!~, :eql?, :hash, :&amp;lt;=&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :class, :singleton_class, :clone, :dup, :itself, :taint,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :frozen?, :to_s, :inspect, :methods, :singleton_methods,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :protected_methods, :private_methods, :public_methods,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :instance_variables, :instance_variable_get,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :instance_variable_set, :instance_variable_defined?,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :remove_instance_variable, :instance_of?, :kind_of?, :is_a?,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :tap, :send, :public_send, :respond_to?, :extend, :display,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :method, :public_method, :singleton_method,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :define_singleton_method, :object_id, :to_enum, :enum_for,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :==, :equal?, :!, :!=, :instance_eval, :instance_exec,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    :__send__, :__id__]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And actually, &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt; didn’t really define any of those itself. It inherited some from &lt;code class=&quot;highlighter-rouge&quot;&gt;BasicObject&lt;/code&gt; and then included &lt;code class=&quot;highlighter-rouge&quot;&gt;Kernel&lt;/code&gt; to get the rest. When you include a module, it’s inserted into the list immediately after the singleton class, which explains the end of the &lt;code class=&quot;highlighter-rouge&quot;&gt;#ancestors&lt;/code&gt; list. Our whole object setup looks like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;       +-------------+
       | BasicObject |
       |   #==       |
       |   #!        |
       |   ...       |
       +-------------+
            ^
            |
            |      +----------+
            |      | Kernel   |
            |      |   #nil?  |
            |      |   #===   |
            |      |   ...    |
            |      +----------+
            |           ^
            |           |
            +-----+-----+
                  |
             +----------+
             | Object   |
             +----------+
                  ^
                  |
                  |
                  |
             +----------+
             | Duck     |
             |   #quack |
             +----------+
                  ^
                  |
                  |
                  |
           +---------------+
duck ~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |
           |   #quack      |
           +---------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is now everything we can look at to decide how &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt; responds to a message. But what about class methods on &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt;? Well, remember I said everything in Ruby is an &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt; - that means everything in our diagram is like &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt;, and has a singleton class and ancestry chain. In fact, everything here except for &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Kernel&lt;/code&gt; are instances of &lt;code class=&quot;highlighter-rouge&quot;&gt;Class&lt;/code&gt;, so we can build them out the same way we built &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;Kernel&lt;/code&gt; is an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;Module&lt;/code&gt;, and has the appropriate singleton class with &lt;code class=&quot;highlighter-rouge&quot;&gt;Module&lt;/code&gt; as its superclass, but drawing that makes the diagram pretty messy.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                      +--------+
                                      | Module |
                                      +--------+
                                          ^
                                          |
                                      +-------+
                                      | Class |
                                      +-------+
                                          ^
                                          |
       +-------------+         +----------------------+
       | BasicObject | ~~~~~~&amp;gt; | #&amp;lt;Class:BasicObject&amp;gt; |
       +-------------+         +----------------------+
            ^                             ^
            |                             |
            |      +----------+           |
            |      | Kernel   |           |
            |      +----------+           |
            |           ^                 |
            |           |                 |
            +-----+-----+                 |
                  |                       |
             +----------+        +-----------------+
             | Object   | ~~~~~&amp;gt; | #&amp;lt;Class:Object&amp;gt; |
             +----------+        +-----------------+
                  ^                       |
                  |                       |
                  |                       |
                  |                       |
               +------+           +---------------+
               | Duck | ~~~~~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |
               +------+           +---------------+
                  ^
                  |
                  |
                  |
           +---------------+
duck ~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |
           +---------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When you define a class method on &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt;, you’ve probably noticed, but maybe sort of glossed over, that you declare it on &lt;code class=&quot;highlighter-rouge&quot;&gt;self&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Duck&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Return all the Ducks in lake&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is no different than when we &lt;code class=&quot;highlighter-rouge&quot;&gt;def duck.quack&lt;/code&gt;ed to put a new method on &lt;code class=&quot;highlighter-rouge&quot;&gt;duck&lt;/code&gt; (but not &lt;code class=&quot;highlighter-rouge&quot;&gt;other_duck&lt;/code&gt;). In this context, &lt;code class=&quot;highlighter-rouge&quot;&gt;self&lt;/code&gt; is &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck&lt;/code&gt;, so we’re stashing &lt;code class=&quot;highlighter-rouge&quot;&gt;.in&lt;/code&gt; on &lt;code class=&quot;highlighter-rouge&quot;&gt;Duck.singleton_class&lt;/code&gt; in exactly the same way.&lt;/p&gt;

&lt;h3 id=&quot;all-together-now&quot;&gt;All together now&lt;/h3&gt;

&lt;p&gt;Ok, one more iteration. Once again, everything is an &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt; - even &lt;code class=&quot;highlighter-rouge&quot;&gt;Module&lt;/code&gt;. You can discard that time traveling ancestry paradox from before, and we’ll just add lines for the actual paradox.&lt;/p&gt;

&lt;div class=&quot;small-example highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                                                +----------+
                                                                |          |
                                      +--------+       +-----------------+ |
   +----------------------------------| Module | ~~~~&amp;gt; | #&amp;lt;Class:Module&amp;gt; | |
   |                                  +--------+       +-----------------+ |
   |                                      ^                     ^          |
   |                                      |                     |          |
   |                                  +-------+         +----------------+ |
   |                                  | Class | ~~~~~~&amp;gt; | #&amp;lt;Class:Class&amp;gt; | |
   |                                  +-------+         +----------------+ |
   |                                      ^                                |
   |                                      |                                |
   |   +-------------+         +----------------------+                    |
   |   | BasicObject | ~~~~~~&amp;gt; | #&amp;lt;Class:BasicObject&amp;gt; |                    |
   |   +-------------+         +----------------------+                    |
   |        ^                             ^                                |
   |        |                             |                                |
   |        |      +----------+           |                                |
   |        |      | Kernel   |           |                                |
   |        |      +----------+           |                                |
   |        |           ^                 |                                |
   |        |           |                 |                                |
   |        +-----+-----+                 |                                |
   |              |                       |                                |
   |         +----------+        +-----------------+                       |
   +-------&amp;gt; | Object   | ~~~~~&amp;gt; | #&amp;lt;Class:Object&amp;gt; |                       |
             +----------+        +-----------------+                       |
                  ^                       |   ^                            |
                  |                       |   |                            |
                  |                       |   +----------------------------+
                  |                       |
               +------+           +---------------+
               | Duck | ~~~~~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |
               +------+           +---------------+
                  ^
                  |
                  |
                  |
           +---------------+
duck ~~~~&amp;gt; | #&amp;lt;Class:Duck&amp;gt; |
           +---------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Module&lt;/code&gt; is an &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;, which inherits from &lt;code class=&quot;highlighter-rouge&quot;&gt;BasicObject&lt;/code&gt;, which is a &lt;code class=&quot;highlighter-rouge&quot;&gt;Class&lt;/code&gt;, which inherits from &lt;code class=&quot;highlighter-rouge&quot;&gt;Module&lt;/code&gt;, which is an &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;, and so on until you hit the turtles. &lt;code class=&quot;highlighter-rouge&quot;&gt;#ancestors&lt;/code&gt; and other methods that would have trouble with this loop have special cases in the Ruby source for when they find &lt;code class=&quot;highlighter-rouge&quot;&gt;BasicObject&lt;/code&gt;, and just pretend that’s the end of the line.&lt;/p&gt;

&lt;p&gt;If you start from any of these objects and traverse up, right-to-left, depth-first, you can build the ancestry chain showing in what order methods will be found. Everything has a singleton class to handle the things we declare on it, and there’s only a little bit of cheating to make the whole thing work. But what did you expect from a system filled with ducks?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author: Kristján Pétursson&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Gems != Magic</title>
   <link href="https://jakeyesbeck.com/2015/08/16/gems-are-not-magic/"/>
   <updated>2015-08-16T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/08/16/gems-are-not-magic</id>
   <content type="html">&lt;p&gt;Ruby gems can seem magical. Usually, one (or more accurately: thirty) solution to a problem exists in the form of a gem. Using gems is easy and intuitive. Simply add a line in the project root’s &lt;code class=&quot;highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt; and run &lt;code class=&quot;highlighter-rouge&quot;&gt;bundle install&lt;/code&gt;. Then, either &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt; the name of the gem or, if using Ruby on Rails, start using the gem’s code immediately anywhere in the project. What could possibly go wrong?&lt;/p&gt;

&lt;h2 id=&quot;gems-on-gems-on-gems&quot;&gt;Gems on gems on gems&lt;/h2&gt;

&lt;p&gt;Unchecked and unmanaged, a project’s &lt;code class=&quot;highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt; might turn into something that looks like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;https://rubygems.org&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;linkbuilder&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http_helper&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;the-color-red&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;devise&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;cancancancancan&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;nokogiri&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;crack&#39;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ....&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# .....&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;cucumber&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;avacado&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;you-get-the-idea&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;these-are-too-many-gems&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;really&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It is very possible that all these gems do not have any adverse side effects. They might not even have any horrible monkey patches to &lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;. &lt;a href=&quot;https://www.nateberkopec.com/2015/07/22/secrets-to-speedy-ruby-apps-on-heroku.html&quot;&gt;This post&lt;/a&gt; has more information on &lt;em&gt;“Why do most Rails apps use so much memory per process?”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Without being able to see inside of them, intrusive gems might be mixed into this mass and we would have no idea. At a glance, it is not immediately obvious how to differentiate between benign and malignant gems. It becomes infinitely easier to understand how gems interact if we remember that gems are not magic.&lt;/p&gt;

&lt;h2 id=&quot;gems-are-just-libraries&quot;&gt;Gems are just Libraries&lt;/h2&gt;

&lt;p&gt;There it is! The rabbit is out of the hat. Somewhere, some amount of cats have been released from their respective bags. Gems are not magic silver bullets injected into a codebase. Instead &lt;strong&gt;they are nothing more than libraries of code&lt;/strong&gt;. Gems are &lt;em&gt;(hopefully)&lt;/em&gt; well encapsulated groups of files that amount to a &lt;em&gt;(again hopefully)&lt;/em&gt; few pieces of helpful functionality. With this new understanding of what gems really are, it means that parsing, modifying, and creating gems is within reach. All that is left is to figure out how to pry them open.&lt;/p&gt;

&lt;h2 id=&quot;opening-gems&quot;&gt;Opening gems&lt;/h2&gt;

&lt;p&gt;Understanding gems is a great way to learn different design patterns and idiomatic Ruby conventions. Good gems have &lt;a href=&quot;https://github.com/jnunemaker/httparty/blob/master/lib/httparty.rb#L29&quot;&gt;in-line documentation&lt;/a&gt;, great gems have &lt;a href=&quot;https://github.com/apotonick/trailblazer#trailblazer&quot;&gt;comprehensive Github documentation&lt;/a&gt;. Github is the most common place to find the source code for gems and a large number of them have really great method and API documentation. This level of detail might be all that is required; however, for the more opaque gems, the &lt;code class=&quot;highlighter-rouge&quot;&gt;bundle open&lt;/code&gt; command is extremely helpful.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bundle open &amp;lt;gemname&amp;gt;&lt;/code&gt; will use the system default text editor to open the contents of a gem. Since all gems are installed locally on the system, they should be available to open from a project’s root. If a default editor is not set, or the default is not desired, one can be added to the beginning of the command: &lt;code class=&quot;highlighter-rouge&quot;&gt;EDITOR=vim bundle open &amp;lt;gemname&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A common starting place for a gem’s logic is in a file with the same name as the gem. Since most gems need to encapsulate their logic, a namespace or wrapper class is usually created with the same name as the gem. In this file it is equally common to find a list of required files or the entry point for the underlying logic. This file is usually in the root of the gem’s source or in a &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;https://jakeyesbeck.com/2015/05/10/validates-type/&quot;&gt;validates_type&lt;/a&gt; root file:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/validates_type_dir_list.png&quot; alt=&quot;validates_type dir list&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;great-now-what&quot;&gt;Great! Now what?&lt;/h2&gt;

&lt;p&gt;Now, go out there and open up all the gems in the entire world! Read them, understand them, be one with the gems. Get a flavor for the different types of Ruby code that can exist. Then, after complete code nirvana has been achieved, submit a pull request to the gem’s source with some great additions. Or, place a few bindings in a few obscure methods to see how the code flows in and out of the gem. A master craftsman understands all of the tools in his toolbox, the same should be true for software.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Process Large Data Sets with Ruby</title>
   <link href="https://jakeyesbeck.com/2015/08/09/how-to-process-large-data-sets-with-ruby/"/>
   <updated>2015-08-09T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/08/09/how-to-process-large-data-sets-with-ruby</id>
   <content type="html">&lt;p&gt;The need for data migrations in mature systems is real. At times, requests for these migrations can appear at random. One minute, a system is behaving as specified, happily fulfilling requests, and then bam! All the user objects suddenly need an extremely crucial attribute. Well that seems relatively simple, right? All that is needed is a simple ruby script to iterate over all users and update every user with this essential piece of data.&lt;/p&gt;

&lt;p&gt;To demonstrate such a problem, we can assume the following:&lt;/p&gt;

&lt;p&gt;A Ruby on Rails application exists with a &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; class, each with a &lt;code class=&quot;highlighter-rouge&quot;&gt;phone_number&lt;/code&gt; attribute.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;validates_presence_of&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:phone_number&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The application is relatively popular, which results in 2,000,000 &lt;code class=&quot;highlighter-rouge&quot;&gt;users&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;count&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 2000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Finally, the requested task:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a “+1” to the beginning of all user phone numbers (we are assuming that all phone numbers belong to users in the USA or Canada).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: Ruby is probably not the best tool for this kind of data migration but for argument’s sake we can assume it is the only one available.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;serial-scripts-at-scale-are-slow&quot;&gt;Serial scripts at scale are slow&lt;/h2&gt;

&lt;p&gt;Without giving it too much thought, an approach to solve this problem might look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;phone_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;+1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;phone_number&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This approach will work. The &lt;a href=&quot;https://guides.rubyonrails.org/active_record_querying.html#find-each&quot;&gt;find_each&lt;/a&gt; method will make sure the memory footprint of the script stays low (it will not load every user into memory at once) and the phone numbers will be updated.&lt;/p&gt;

&lt;p&gt;However, this will be painfully slow. Even if the system is able to update 20 users per second, it will take approximately &lt;strong&gt;27 hours&lt;/strong&gt; to complete.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2,000,000 users / 20 users per second
= 100,000 seconds to process all users
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;100,000 seconds / 60 seconds
~= 1,666 minutes
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1,666 minutes / 60 minutes
~= 27 hours
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;resque-to-the-rescue&quot;&gt;Resque to the Rescue&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/resque/resque&quot;&gt;Resque&lt;/a&gt; is a very useful Ruby library for creating background jobs. Redis is utilized as the storage for these jobs and individual Resque workers pick one job off each queue at a time.&lt;/p&gt;

&lt;p&gt;With a small amount of code reorganization, Resque enables processing multiple users &lt;strong&gt;at the same time&lt;/strong&gt;. The basic idea behind this approach is divide and conquer.&lt;/p&gt;

&lt;h3 id=&quot;install-resque-and-redishttpsredisiotopicsquickstart&quot;&gt;0. Install Resque and &lt;a href=&quot;https://redis.io/topics/quickstart&quot;&gt;Redis&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id=&quot;extract-phone-number-updates-into-a-new-class&quot;&gt;1. Extract phone number updates into a new class&lt;/h3&gt;

&lt;p&gt;This new class will accept a single &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; and update all associated &lt;code class=&quot;highlighter-rouge&quot;&gt;phone_numbers&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PhoneUpdater&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_phone!&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;phone_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;+1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;phone_number&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;create-a-resque-job-to-use-this-logic&quot;&gt;2. Create a Resque Job to use this logic&lt;/h3&gt;

&lt;p&gt;A Resque Job class needs to conform to a simple API. A &lt;code class=&quot;highlighter-rouge&quot;&gt;queue&lt;/code&gt; must be defined and the class must have a class method named &lt;code class=&quot;highlighter-rouge&quot;&gt;perform&lt;/code&gt;. The parameter given to &lt;code class=&quot;highlighter-rouge&quot;&gt;perform&lt;/code&gt; is the same that is passed to Resque when a job is enqueued.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PhoneUpdaterJob&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@queue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:phone_updates&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;perform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;updater&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PhoneUpdater&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;updater&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_phone!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;create-script-to-enqueue-resquejobs&quot;&gt;3. Create script to enqueue ResqueJobs&lt;/h3&gt;

&lt;p&gt;Iterate over the user set and enqueue a job per user. The second argument is the &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; of the user to process.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Resque&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enqueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;PhoneUpdaterJob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;run-many-parallel-resque-workers&quot;&gt;4. Run many parallel Resque workers&lt;/h3&gt;

&lt;p&gt;This is where the fun happens. By initializing many different Resque worker processes, they all will read from the &lt;code class=&quot;highlighter-rouge&quot;&gt;phone_updates&lt;/code&gt; queue and process users in parallel. The &lt;code class=&quot;highlighter-rouge&quot;&gt;QUEUE&lt;/code&gt; specified matches what was defined in &lt;code class=&quot;highlighter-rouge&quot;&gt;PhoneUpdaterJob&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Open a terminal in the root of your project...&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;QUEUE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;phone_updates rake resque:work

&lt;span class=&quot;c&quot;&gt;# Open another terminal in the root of your project...&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;QUEUE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;phone_updates rake resque:work

&lt;span class=&quot;nv&quot;&gt;QUEUE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;phone_updates rake resque:work
&lt;span class=&quot;c&quot;&gt;# Open another terminal in the root of your project...&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;try-not-to-overload-the-system&quot;&gt;5. Try not to overload the system&lt;/h3&gt;

&lt;p&gt;Now with 2,000,000 queued Resque jobs, each Resque worker will drastically decrease the execution time of the overall task. However, system constraints should not be ignored. Database connection saturation, CPU usage and memory usage should be used in calculation of how many Resque workers to run at once.&lt;/p&gt;

&lt;h2 id=&quot;parallelism-is-awesome&quot;&gt;Parallelism is awesome&lt;/h2&gt;

&lt;p&gt;Although the parallel solution is not as simple as its serial counterpart, the benefits are extremely apparent. The parallel solution is not without its weaknesses, but they do not make it invalid. It iterates over the entire user set twice, but parallelizing the slow &lt;code class=&quot;highlighter-rouge&quot;&gt;phone_number&lt;/code&gt; update queries makes up for that inefficiency ten-fold.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Faster Ruby Testing: Only Test What Matters</title>
   <link href="https://jakeyesbeck.com/2015/08/02/test-only-what-matters/"/>
   <updated>2015-08-02T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/08/02/test-only-what-matters</id>
   <content type="html">&lt;p&gt;Automated testing is important. Fast, exhaustive automated testing is even more important. Tests are responsible for ensuring the code you spend hours creating actually works. A great test suite can be a safeguard against bugs, a directional guide towards extending the code, and an accurate measurement of the codebase’s health. The key to writing good tests is understanding where pieces of responsibility begin and end. Maintaining small concise automated tests can make all the difference.&lt;/p&gt;

&lt;h2 id=&quot;speed-is-king&quot;&gt;Speed is King&lt;/h2&gt;

&lt;p&gt;Aside from the general importance of &lt;a href=&quot;https://jakeyesbeck.com/2015/06/07/short-feedback-cycles/&quot;&gt;short feedback cycles&lt;/a&gt;, a fast test suite will greatly improve your work-flow and mood. Conversely, a slow test suite can make your development cycle a living nightmare. How many unfortunate software artisans have dealt with something like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/slow_tests.png&quot; alt=&quot;slow test suite screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bleh! What a horrible thing to deal with. What, am I supposed to just wait 5 whole minutes every time I want to test my system? A test suite this slow is simply unacceptable.&lt;/p&gt;

&lt;p&gt;So what could be causing this slowness? More than likely, a number of tests in this application are doing too much. To try and replicate and solve this problem, let’s assume we have a Ruby on Rails application we test using RSpec.&lt;/p&gt;

&lt;h2 id=&quot;testing-database-models-is-slow&quot;&gt;Testing Database Models is Slow&lt;/h2&gt;

&lt;p&gt;We can assume that there exists a very important class called &lt;code class=&quot;highlighter-rouge&quot;&gt;MyAwesomeClass&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyAwesomeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assign_and_save!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;saved_on_the_weekend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weekend?&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;weekend?&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;saturday?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sunday?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If we wanted to test that the &lt;code class=&quot;highlighter-rouge&quot;&gt;assign_and_save!&lt;/code&gt; method works correctly, we might write a test like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#assign_and_save!&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;assigns and saves&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyAwesomeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assign_and_save!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MyAwesomeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;saved_on_the_weekend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be_nil&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;These tests make sure that the model is saved correctly to the database and a value is assigned to &lt;code class=&quot;highlighter-rouge&quot;&gt;saved_on_the_weekend&lt;/code&gt;. However, the test code is overstepping the boundaries of the method it is testing. The &lt;code class=&quot;highlighter-rouge&quot;&gt;assign_and_save!&lt;/code&gt; method’s job is to simply assign a value to an object and then save it. It does not care about how the actual saving works, that is the job of other validations on the model and &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To avoid this, we can assert that the &lt;code class=&quot;highlighter-rouge&quot;&gt;save!&lt;/code&gt; method is called, which will not actually write to our database:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#assign_and_save!&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;assigns and saves&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyAwesomeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:save!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assign_and_save!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;saved_on_the_weekend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be_nil&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Voila! We have made the same assertions about our code and did not do any slow input/output operations.&lt;/p&gt;

&lt;p&gt;Now I know what some of the more detail oriented Software Artisans reading this will initially think: &lt;em&gt;“What about validation concerns with the model?”&lt;/em&gt; and &lt;em&gt;“If you stub out &lt;code class=&quot;highlighter-rouge&quot;&gt;save!&lt;/code&gt; like that you can’t be sure it worked”&lt;/em&gt;. While these are totally valid points, there exists a simple solution for dealing with the uncertainty of the save:&lt;/p&gt;

&lt;h2 id=&quot;the-valid-method&quot;&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;valid?&lt;/code&gt; method&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;#assign_and_save!&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;assigns and saves&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyAwesomeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:save!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assign_and_save!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;saved_on_the_weekend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be_nil&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;is save-able&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyAwesomeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:save!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assign_and_save!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be_valid&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With the new test assertion, we make sure that the model’s &lt;code class=&quot;highlighter-rouge&quot;&gt;valid?&lt;/code&gt; method returns true, ensuring the model will be saved properly.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;valid?&lt;/code&gt; method is what &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; uses before saving the model to the database. This method returns either &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt; and writes the data to the database if &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; was returned. Now the code is tested and &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;’s’ validation errors are considered.&lt;/p&gt;

&lt;h2 id=&quot;not-perfect-but-good-enough&quot;&gt;Not Perfect, but Good Enough&lt;/h2&gt;

&lt;p&gt;However, there is one more thing that this test will not catch: database specific uniqueness constraints. If your application uses a database to enforce uniqueness and not in &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; validations, this testing method will fail. For that you will need a more robust integration tests which guard against duplicate data.&lt;/p&gt;

&lt;p&gt;All that aside, not actually saving data will be fine for the 90% case which is most codebases.&lt;/p&gt;

&lt;h2 id=&quot;only-test-what-matters&quot;&gt;Only Test What Matters&lt;/h2&gt;

&lt;p&gt;In this example, removing the testing of &lt;code class=&quot;highlighter-rouge&quot;&gt;save!&lt;/code&gt; resulted in a speed increase. However, the idea of only testing the crucial parts of a method is not only about speed, &lt;strong&gt;it is about encapsulation&lt;/strong&gt;. If a method’s only responsibility is to call helper methods, that is the only thing that should be tested. The test should simply assert that the helper methods are called, not the logic within them. Following this pattern will help keep test code small, concise, readable, and input/output operations to a minimum.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ninety Days of Commits</title>
   <link href="https://jakeyesbeck.com/2015/07/26/ninety-days-of-commits/"/>
   <updated>2015-07-26T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/07/26/ninety-days-of-commits</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/90_day_streak.png&quot; alt=&quot;90 Days of Commits&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It has been ninety days since I started the &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt; initiative. The criteria behind this challenge was to make a commit to a public Github repository every day. Technically, a commit like the following satisfies that criteria:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/example_small_commit.png&quot; alt=&quot;Small daily commit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, if I allowed this commit to be my sole contribution for a day, I would be cheating no one except myself. In reality, I have been averaging 3 to 4 decent size commits a day. Spending around an hour or two total per night. Github is an awesome piece of software that tells a visual tale of when I am most productive:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://jakeyesbeck.com/assets/images/time_of_commits.png&quot; alt=&quot;Times of Commits&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Over this quarter of a year, I have accrued some interesting learnings about developing open source software.&lt;/p&gt;

&lt;h2 id=&quot;writing-software-every-day-just-feels-good&quot;&gt;1. Writing software every day just feels good.&lt;/h2&gt;

&lt;p&gt;Not missing a single day of writing software has made a significant improvement in my confidence and attitude. In the same way exercising daily makes your body feel more sturdy, developing software daily keeps my mind focused and clear. Like warming up a car before a drive, writing software every day makes it very easy for me to jump into a new project or build a new feature. I think most of my fellow software artisans have been in this situation: You go on vacation or maybe just a very relaxing weekend, then the next day at work or when you open that side project again, you end up spending a lot of time getting familiar with the software. Even if you just wrote it a few days ago, the break has made some tiny details less sharp. Writing software every single day helps eliminate this.&lt;/p&gt;

&lt;h2 id=&quot;immature-software-is-expected&quot;&gt;2. Immature software is expected&lt;/h2&gt;

&lt;p&gt;While writing software, there are a total of 0 people that look at what they just wrote and say: “This software is already bad and I have only just written it”. However, this statement can be more true than we would like. The potential in a new project is always the best part, right? Developers around the world usually jump at a change to do green field development. After all, with no legacy software around we can make what ever our heart desires. It can be clean, DRY, clever software with all the best design patterns. But, at least in my experience, all software starts off painfully immature. This is just fine. The shape and structure of good software grows over time. This is particularly true for my Year of Commits projects. Since I must write software every single day, I revisit my software extremely frequently. This re-visitation greatly increases the iterations my software goes through and I end up with much more polished work.&lt;/p&gt;

&lt;h2 id=&quot;software-development-is-not-just-making-it-work&quot;&gt;3. Software development is not just making it work&lt;/h2&gt;

&lt;p&gt;If you take away business requirements, deadlines, conversion rates, etc., you are left with something pure: software development. Year of Commits has enabled me to experience developing software at a slower pace without these extra degrees of “purpose”. Because of this, I have learned the difference between software that just works and carefully architect-ed software. I am not boasting that the software I write is now amazingly designed and executed, I have just noticed that when I invest more time, it makes a difference. We, as Software Aristans need time to stop and smell the ones and zeros. Given a decent amount of time and attention, all software can mature to something really extraordinary.&lt;/p&gt;

&lt;p&gt;I am optimistic about completing my goal of a Year of Commits. With 3/4 the distance ahead of me, let’s hope I can keep that graph solid green.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Just learn Rails (Part 2)</title>
   <link href="https://jakeyesbeck.com/2015/07/19/just-learn-rails-part-2/"/>
   <updated>2015-07-19T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/07/19/just-learn-rails-part-2</id>
   <content type="html">&lt;p&gt;In a &lt;a href=&quot;https://jakeyesbeck.com/2015/05/17/just-learn-rails/&quot;&gt;previous post&lt;/a&gt; I explained how &lt;em&gt;“just learning Rails”&lt;/em&gt; is not as straight forward as the phrase portrays. Even the novice programmer who learns Ruby on Rails in a methodical progression may still run into hardship. However, this is not entirely the fault of young programmer, he or she was simply enabled into bad habits. &lt;strong&gt;Ruby on Rails enables the complete disregard of encapsulation.&lt;/strong&gt; Notice how I did not say that Ruby on Rails prescribes less encapsulation, it simply enables it.&lt;/p&gt;

&lt;p&gt;This idea, much like any idea posted to the Internet, is not new. Many intelligent people have come to this same realization. One such example is the &lt;a href=&quot;https://github.com/apotonick/trailblazer&quot;&gt;Trailblazer framework&lt;/a&gt;, which aims to help inject some encapsulation and abstraction mechanisms Rails is lacking. (For those interested, &lt;a href=&quot;https://leanpub.com/trailblazer&quot;&gt;a book has been written&lt;/a&gt; to more fully explain this framework).&lt;/p&gt;

&lt;p&gt;Alright, so what am I really talking about? Ruby on Rails has certain features that make it easy to forget about encapsulation.&lt;/p&gt;

&lt;h3 id=&quot;the-autoloader&quot;&gt;The Autoloader&lt;/h3&gt;

&lt;p&gt;A keyword that most Ruby on Rails developers rarely see on a daily basis is &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt;. A piece of Ruby on Rails magic called &lt;a href=&quot;https://guides.rubyonrails.org/autoloading_and_reloading_constants.html&quot;&gt;autoloading&lt;/a&gt; greatly decreased the frequency of the &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt; keyword in Ruby on Rails applications. This has many positive aspects for new and seasoned developers alike. But, it is not without drawbacks. One such drawback is that it makes &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; objects ubiquitous. Whenever a developer has the urge to reach into the database, regardless of the context, they are able to do so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This enables horrific code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine we have a view template that we want to display a user’s username and their pictures. Without any guidance, this following code could come into existence:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#
# Reminder, this is terrible code. Never do this.
#

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!--
    Let&#39;s just go through all the users in the database.
    This is a new application so we don&#39;t have that many users,
     it will never run into scalability issues.
     --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;username&#39;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;pictures&#39;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!--
       Make sure we have the only the picture url, just go ahead
        directly to the database and let it handle
        the downcasing that we, for some reason, need.
       Also, Jim in Business Ops thinks it will be
        super great to order the pictures randomly each time!
      --&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Pictures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;downcase(url)&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;random()&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

#
# Never replicate the above code or you will be very sad
#
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Notice how deep in the presentation layer (the view) we have direct database calls. This completely violates the encapsulations that an MVC framework should provide. Since all the models exist everywhere, nothing stops a programmer from writing it in this way. The code above should make every ruby programmer cringe.&lt;/p&gt;

&lt;p&gt;Separating concerns and responsibilities helps prevent repetition and boosts comprehension. The above code should be a composition of multiple objects with entirely different responsibilities. That concept is not always intuitive for some developers, especially those just starting out. One might ask: &lt;em&gt;“Why would I make a whole mess of objects to do the same thing that these 14 lines can do?”&lt;/em&gt;. The simple answer is because these problems are not new. Ruby on Rails did not expose these abstraction and encapsulation issues for the first time in the history of software engineering. They have been around for &lt;a href=&quot;https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)&quot;&gt;a very long time&lt;/a&gt;. Smarter software artisans than I saw these problems and created guidelines to solve them. Following their lead will save all of us in the long run.&lt;/p&gt;

&lt;p&gt;So what can we do about our misguided code above? Let us try moving some responsibilities around and see how it changes.&lt;/p&gt;

&lt;h3 id=&quot;add-a-dash-of-encapsulation&quot;&gt;Add a dash of encapsulation&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# The user class just needs to know about the database connection.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ActiveRecord takes care of that detail for us, adding a scope&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   is a supplementary addition to that logic.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:with_pictures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:pictures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# We can create a PORO (Plain Old Ruby Object) to house the user&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#  object and extract, downcase, and randomize its picture urls.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserPresenter&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@pictures&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pictures&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;username&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;username&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;picture_urls&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@pictures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;photo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;photo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downcase&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shuffle&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# The controller handles linking up each User with a UserPresenter&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#  then saves the list to a variable to be used by the view.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UsersController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user_presenters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_pictures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@user_presenters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UserPresenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Finally, the view logic only knows about a presenter for each user. From the views perspective, the presenter object only has two methods: username and picture_urls. It does not need to know about database structure, schema, syntax or business logic. It has one job, to display data:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user_presenters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;presenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;username&#39;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;presenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;pictures&#39;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;presenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;picture_urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;The code that was rewritten is far from perfect. However, it is a noticeable improvement over its original version. I am in no way claiming to be the creator of these design patters, simply a spokesperson for good encapsulation and object oriented design. When respected and correctly utilized, Ruby on Rails is a fantastic tool for web development. When learning Ruby on Rails, it is imperative to stand by software engineering paradigms. Just because a framework allows it, doesn’t mean that it is necessarily a good thing to do.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Create a Free Tech Blog</title>
   <link href="https://jakeyesbeck.com/2015/07/12/create-a-free-tech-blog/"/>
   <updated>2015-07-12T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/07/12/create-a-free-tech-blog</id>
   <content type="html">&lt;p&gt;The Internet is wondrous technology. If anyone remembers Geocities and Personal Home Pages, you can appreciate just how much the Internet has evolved. This evolution has recently enabled creating a tech blog completely for free. When I say free, do I mean completely free? Yes, completely free! Even this very blog, my Year of Commits, is hosted for free using the same technologies outlined in this post. You too can have a free tech blog after following these &lt;strong&gt;2 simple steps&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;step-1-use-jekyll&quot;&gt;Step 1. Use Jekyll&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; is a free open source static site generator. The Jekyll documentation page has some great &lt;a href=&quot;https://jekyllrb.com/docs/quickstart/&quot;&gt;tutorials&lt;/a&gt; that make getting started extremely painless. Jekyll is also a ruby tool. To contribute to Jekyll, check out their &lt;a href=&quot;https://github.com/jekyll/jekyll&quot;&gt;github page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jekyll makes it easy to start creating content without worrying about CSS, page templates, or link architecture. It even generates an RSS feed of your content. All pages can be written in Markdown and automatically converted to HTML upon building or serving the site. The &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll build&lt;/code&gt; command is what this post will focus on, but &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt; is worth checking out too.&lt;/p&gt;

&lt;p&gt;To get started with Jekyll:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$: gem install jekyll
$: jekyll new mytechblog
$: cd mytechblog/
$: touch _posts/2015-07-12-my-first-post.markdown
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will create a new directory with some default configuration files and subdirectories. Inside this new directory, the example created a &lt;code class=&quot;highlighter-rouge&quot;&gt;2015-07-12-my-first-post.markdown&lt;/code&gt; file within the &lt;code class=&quot;highlighter-rouge&quot;&gt;_posts/&lt;/code&gt; subdirectory. This file will contain the content for the first blog post.&lt;/p&gt;

&lt;p&gt;Jekyll Markdown pages require a specific format at the top of the file. This format is called &lt;a href=&quot;https://jekyllrb.com/docs/frontmatter/&quot;&gt;front matter&lt;/a&gt;. It is imperative that all Jekyll posts have proper front matter in order to be converted to HTML.&lt;/p&gt;

&lt;h2 id=&quot;step-2-use-github-pages&quot;&gt;Step 2. Use Github Pages&lt;/h2&gt;

&lt;p&gt;Github has been a great tool for managing version controlled software for years. Now, Github has released an equally awesome tool called &lt;a href=&quot;https://pages.github.com/&quot;&gt;Github Pages&lt;/a&gt;. To get started with Github Pages, simply create a &lt;strong&gt;public&lt;/strong&gt; repository with the pattern: &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;yourusername&amp;gt;.github.io&lt;/code&gt; (Remember to replace the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;yourusename&amp;gt; &lt;/code&gt; with your actual username). Now, every time a commit is pushed to this repository’s master branch, the blog will be automatically updated. Since this repository is required to be public, make sure that no sensitive information is accidentally committed within posts.&lt;/p&gt;

&lt;p&gt;To set up a directory and point it to the github.io repository:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; mkdir username.github.io
&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;username.github.io/
&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; git init .
&lt;span class=&quot;nv&quot;&gt;$:&lt;/span&gt; git remote add origin git@github.com:username/username.github.io.git
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The files uploaded to the Github Pages repository should be static HTML. This is where &lt;strong&gt;Step 1&lt;/strong&gt; comes in. Since this blog will use &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll build&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;yourusername&amp;gt;.github.io&lt;/code&gt; repository should consist of HTML files generated by Jekyll.&lt;/p&gt;

&lt;p&gt;To generate the HTML files:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$: cd mytechblog
$: jekyll build --destination=~/username.github.io
$: cd ~/username.github.io
$: git add .
$: git commit -m &quot;First blog post&quot;
$: git push origin HEAD
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And there you have it! A successful blog created entirely for free. Now, the example blog is accessible at https://username.github.io.&lt;/p&gt;

&lt;h2 id=&quot;optional-step-3-use-a-custom-url&quot;&gt;(Optional) Step 3. Use a custom URL&lt;/h2&gt;

&lt;p&gt;To serve a blog at a custom URL, simply add a single file to the root of the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;yourusername&amp;gt;.github.io&lt;/code&gt; repository. The filename must be &lt;code class=&quot;highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; and it should include a single line: the custom URL.&lt;/p&gt;

&lt;p&gt;An example &lt;code class=&quot;highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mytechblog.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Additionally, the DNS provider that &lt;code class=&quot;highlighter-rouge&quot;&gt;mytechblog.com&lt;/code&gt;’s DNS is served from must include an &lt;code class=&quot;highlighter-rouge&quot;&gt;ALIAS&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;ANAME&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; record to the Github IP. More information on setting a custom domain can be found at the &lt;a href=&quot;https://help.github.com/articles/tips-for-configuring-an-a-record-with-your-dns-provider/&quot;&gt;Github help page&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;final-step-blog-for-free-about-cool-technology&quot;&gt;Final Step: Blog for free about cool technology&lt;/h2&gt;

&lt;p&gt;Now that a completely free blog is newly created, you have the ability to update it as frequently as you choose. Share your knowledge at expeditious paces by simply making commits to a public repository. Never worry about hosting costs, server configuration or deployment again. Simply write Markdown, build static HTML, and commit!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Modules in Ruby</title>
   <link href="https://jakeyesbeck.com/2015/07/05/composition-in-ruby/"/>
   <updated>2015-07-05T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/07/05/composition-in-ruby</id>
   <content type="html">&lt;p&gt;Currently, one hundred percent of &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt;’ commits have been to Ruby repositories. Ruby has many strengths and is a very malleable language. Ruby can be written functionally or object oriented. I tend to lean toward the latter and find myself using a few different patterns regularly. One powerful tool Ruby provides is the use of Modules.&lt;/p&gt;

&lt;h2 id=&quot;modules&quot;&gt;Modules&lt;/h2&gt;

&lt;p&gt;When code is to be shared between classes, a &lt;code class=&quot;highlighter-rouge&quot;&gt;Module&lt;/code&gt; is created to encapsulate the shared functionality. A very simple module looks something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ripe&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;this is ripe!&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;extend&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;extend&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;With the &lt;code class=&quot;highlighter-rouge&quot;&gt;Ripe&lt;/code&gt; module, there are two ways to include its methods in a class. We can &lt;code class=&quot;highlighter-rouge&quot;&gt;extend&lt;/code&gt; the module, which makes the method &lt;code class=&quot;highlighter-rouge&quot;&gt;ripe?&lt;/code&gt; a class method on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Banana&lt;/code&gt; class:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Banana&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Ripe&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; this is ripe!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;include&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Alternatively, we can &lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; the module, making &lt;code class=&quot;highlighter-rouge&quot;&gt;ripe?&lt;/code&gt; an instance method:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Banana&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Ripe&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;banana&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; this is ripe!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;That’s great right? Right! We have methods on methods on methods. As long as we can make modules for our instance and class methods separately, we will be golden. But, what about all the times that we need to define both class and instance methods in one module? Surely it would be crazy to have &lt;code class=&quot;highlighter-rouge&quot;&gt;RipeClassMethods&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;RipeInstanceMethods&lt;/code&gt; right? That looks like amateur hour. There must be a better way.&lt;/p&gt;

&lt;h3 id=&quot;def-selfincluded&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;def self.included&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;A very helpful method for dealing with included modules is the &lt;code class=&quot;highlighter-rouge&quot;&gt;included&lt;/code&gt; class method. This method is built in Ruby and any class has access to it. By using the &lt;code class=&quot;highlighter-rouge&quot;&gt;included&lt;/code&gt; method, it is possible to mix class and instance methods within a single module.&lt;/p&gt;

&lt;p&gt;When using &lt;code class=&quot;highlighter-rouge&quot;&gt;self.included&lt;/code&gt;, we are able to determine which methods are accessible on the instance and on the class. We will use a new inner module named &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassMethods&lt;/code&gt; to encapsulate our desired class methods. In our example below, the single parameter &lt;code class=&quot;highlighter-rouge&quot;&gt;base&lt;/code&gt; is the class in which the &lt;code class=&quot;highlighter-rouge&quot;&gt;Ripe&lt;/code&gt; module is included.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ripe&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Just like in normal module extension,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#  the extend method is used to make all methods in&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#  ClassMethods into proper class methods on base&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ClassMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ClassMethods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;this is ripe!&#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, including the functionality from &lt;code class=&quot;highlighter-rouge&quot;&gt;Ripe&lt;/code&gt; is the same as the &lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; example above:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Banana&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Ripe&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; this is ripe!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With this new structure, adding instance methods is as simple as adding them outside of the &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassMethods&lt;/code&gt; module.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ripe&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ClassMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;color&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;yellow&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ClassMethods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;this is ripe!&#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Banana&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Ripe&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ripe?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; this is ripe!&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;banana&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;banana&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; yellow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Boom, boom, pow, we have some nicely organized shared code. We are now able to easily define instance and class methods for our various important fruit related modules.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Staying Motivated</title>
   <link href="https://jakeyesbeck.com/2015/06/28/staying-motivated/"/>
   <updated>2015-06-28T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/06/28/staying-motivated</id>
   <content type="html">&lt;p&gt;Motivation is the most important thing you can control. Only with proper motivation can one reach their full potential. &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;A Year of Commits&lt;/a&gt; is a project that requires a decent amount of motivation. I, like nearly every human ever, am not always the defintion of a “driven individual”. It takes a large amount of effort to persevere through low points and come out the other side with something to show for it. It has been &lt;strong&gt;63&lt;/strong&gt; days of my Year of Commits initiative and I have found a few helpful ways to keep my motivation up and morale high.&lt;/p&gt;

&lt;h2 id=&quot;make-small-deliverables-for-yourself&quot;&gt;1. Make small deliverables for yourself&lt;/h2&gt;

&lt;p&gt;If you embark on grandiose endeavors frequently, consider breaking pieces of them apart into small, digestible morsels of motivation goodness. Every project does not need to go at break neck speed instantly. This is especially applicable in software development. You know that project that you’ve been planning? The revolutionary one that you’re so excited about? That project has a greater chance of completion if you don’t expect finish the whole thing in an afternoon. Setting yourself up with unreasonable expectations can deflate even the most cocksure individuals. If you take some time to prioritize small deliverable pieces, you will be much more likely to achieve something. Speaking from experience, there comes a time when you have to sit back and wonder: &lt;em&gt;“Why do I have 10-15 projects around 30% completion?”.&lt;/em&gt; It might just be that you were biting off a bit more than you can chew. Take smaller bites, you will get there if you just keep going.&lt;/p&gt;

&lt;h2 id=&quot;keep-moving&quot;&gt;2. Keep moving&lt;/h2&gt;

&lt;p&gt;A complementary behavior to breaking things into smaller pieces is to make every day count. As the person committed to working every single day for year, I might be a &lt;em&gt;tad&lt;/em&gt; biased. However, I believe that maintaining at least some kind of constant pace of effort will keep motivation from dropping off a cliff. Procrastination is the greatest enemy of motivation. If you let yourself delay your tasks once, it becomes increasingly easy to delay them again. Subsequent delays will mostly likely be in the not so distant future. If you make your tasks part of your routine, it can have the opposite effect. I bet you don’t even think about all the time you spend doing things that are just “part of your routine”. Imagine if the task you want to accomplish, the world changing, earth shattering, unbelievable awesome project that you have queued up was as easy to fit into your schedule as brushing your teeth. There exists no magic that some of the greatest achievers have found and harnessed. They simply kept working until the job was done. To them, working on what mattered to them was as routine as brushing their teeth or putting on their shoes.&lt;/p&gt;

&lt;h2 id=&quot;believe-that-you-are-good-at-what-you-do&quot;&gt;3. Believe that you are good at what you do&lt;/h2&gt;

&lt;p&gt;As it so happens, your kindergarten teacher was right about a thing or two. Attitude is important in order to help you stay motivated. A self debilitating mindset can vacuum the motivation out of nearly anything. Having the right attitude will help you soar, help keep that fire of motivation stoked and ready. Impostor syndrome, doubts, or anything in that general mindset will be nothing but a hindrance. Understanding your skill sets, knowing where you want to improve and where you have strengths, will help keep you motivated to achieve your goals. This might be the most obvious piece of advice but that does not mean it is the easiest to achieve. In software development, our confidence in our abilities is constantly tested. I try and combat this by remaining calm, remembering &lt;a href=&quot;https://jakeyesbeck.com/2015/06/14/you-are-not-your-code/&quot;&gt;“I am not my code”&lt;/a&gt;, and taking a few deep breaths now and again. Confidence takes time to build. If you are among the lucky few that simply have it in abundance, great news, you just need to keep it strong!&lt;/p&gt;

&lt;p&gt;So now with all this new information, ask yourself: Are &lt;em&gt;you&lt;/em&gt; good? Yeah you are good. You are better than good, you’re motivated! Keep moving, keep building, keep creating and you will get to where you want to go. You are the one at the helm, the one in control of your journey. Motivation is the fuel.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails style subset validation</title>
   <link href="https://jakeyesbeck.com/2015/06/21/validates-subset/"/>
   <updated>2015-06-21T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/06/21/validates-subset</id>
   <content type="html">&lt;p&gt;Do you suddenly wake up in a cold sweat, wondering if there is &lt;strong&gt;finally&lt;/strong&gt; a way to validate that your data is a proper subset that you desire? I too have experienced this horror, and that is why I made a rails style &lt;a href=&quot;https://github.com/yez/validates_subset&quot;&gt;subset validator&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;validations-ber-alles&quot;&gt;Validations über alles&lt;/h2&gt;

&lt;p&gt;Data validation is important. Having data you can depend on is the difference between a great application and one that might be classified as: &lt;em&gt;“amateur hour”&lt;/em&gt;. Rails provides a nice amount of validators via &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel::Validations&lt;/code&gt;, but not an exhaustive set (get it?). One of those missing pieces involves validating sets of data. Just in case you haven’t had your coffee yet, we define a &lt;a href=&quot;https://en.wikipedia.org/wiki/Set_(abstract_data_type)&quot;&gt;set&lt;/a&gt; as an abstract data type that stores distinct values in no particular order.&lt;/p&gt;

&lt;p&gt;Ruby does indeed have the &lt;code class=&quot;highlighter-rouge&quot;&gt;Set&lt;/code&gt; class but most code I’ve come across simply uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt; class. So, for simplicity’s sake, all examples will use &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have all been convinced that subset validation is the greatest thing since sliced bread, how about some examples?&lt;/p&gt;

&lt;h2 id=&quot;example-usage&quot;&gt;Example usage&lt;/h2&gt;

&lt;p&gt;To include &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_subset&lt;/code&gt;, simply add &lt;code class=&quot;highlighter-rouge&quot;&gt;gem &#39;validates_subset&#39;&lt;/code&gt; in your Gemfile of your projects. Or type &lt;code class=&quot;highlighter-rouge&quot;&gt;gem install validates_subset&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;For rails applications, the gem is automagically available to you. For other ruby frameworks, just add the line: &lt;code class=&quot;highlighter-rouge&quot;&gt;require &#39;validates_subset&#39;&lt;/code&gt; wherever you need the library. For this, we can assume that our application is using Rails 4.0 and we have a class that looks like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HasASubset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;validates_subset&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;using-our-handy-dandy-test-class-we-can-see-that&quot;&gt;Using our handy dandy test class, we can see that:&lt;/h2&gt;

&lt;h3 id=&quot;a-valid-subset-is-valid&quot;&gt;A valid subset is valid:&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HasASubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;valid?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;an-empty-set-is-also-very-valid&quot;&gt;An empty set is also very valid:&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HasASubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;valid?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;an-invalid-set-is-invalid&quot;&gt;An invalid set is… invalid:&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HasASubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;banana&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;valid?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;and-a-non-set-is-invalid&quot;&gt;And a non-set is invalid:&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HasASubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99_999&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;valid?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Holy guacamole that is some sweet validation. But wait, there’s more! Since this validator is built on top of rock solid &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel::Validations&lt;/code&gt; logic, all modifiers are supported.&lt;/p&gt;

&lt;h2 id=&quot;modification-nation&quot;&gt;Modification nation&lt;/h2&gt;

&lt;p&gt;If your particular dataset needs something to be a subset or &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;, it is a simple as:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HasASubset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;validates_subset&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;allow_nil: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you needed the data to &lt;code class=&quot;highlighter-rouge&quot;&gt;allow_nil&lt;/code&gt; and only validate on &lt;code class=&quot;highlighter-rouge&quot;&gt;create&lt;/code&gt;, you could easily define the validation as:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HasASubset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;validates_subset&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;allow_nil: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on: :create&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Any combination of modifiers is supported by &lt;code class=&quot;highlighter-rouge&quot;&gt;validates_subset&lt;/code&gt;. For a complete list of modifiers, have a look at the &lt;a href=&quot;https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validate&quot;&gt;rails documentationn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As always, please contribute to and use this software for the low low price of free.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>You are not your code</title>
   <link href="https://jakeyesbeck.com/2015/06/14/you-are-not-your-code/"/>
   <updated>2015-06-14T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/06/14/you-are-not-your-code</id>
   <content type="html">&lt;p&gt;It may have been a mentor, a colleague, or even a random vagrant on your way to work. One of these people has been wise enough in to let you in on the well known fact that: &lt;em&gt;“You are not your code”&lt;/em&gt;. The words themselves seem so simple, so obvious and straightforward. But simple as it may be, this concept is paramount if you are to survive as a &lt;a href=&quot;https://jakeyesbeck.com/2015/05/17/just-learn-rails/&quot;&gt;Software Artisan&lt;/a&gt; and as a functioning member of society.&lt;/p&gt;

&lt;p&gt;When writing software, having a sizable ego is not always appropriate. In fact, it could become a hindrance that will prevent you from being productive and happy. Software contribution is about coordinating with others to make the best possible software. It is very hard to coordinate if a person is unable to relinquish control of their projects because they feel defined by them.&lt;/p&gt;

&lt;p&gt;The first time someone said that I was not my code, I took offense. I didn’t understand what they really meant. All I could think was: &lt;em&gt;“What do you mean? &lt;strong&gt;I&lt;/strong&gt; wrote the code. &lt;strong&gt;I&lt;/strong&gt; put my heart, soul, blood, sweat, and tears into the code. It is the epitome of &lt;strong&gt;me&lt;/strong&gt;. The code &lt;strong&gt;I&lt;/strong&gt; write defines &lt;strong&gt;me!&lt;/strong&gt; “&lt;/em&gt;. It was that last statement that demonstrated how naive I really was. Your code was crafted by you, maintained by you, and evolved with you. But, like a carpenter is not a chair, &lt;strong&gt;you are not your code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;During my &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt;, it has been very important to internalize the difference between my code and myself. If I have too much ownership and pride dealing with the code I write, it makes it impossible for me to contribute as part of a community. The difference between writing software and other creative forms of work lies in the longevity of what is created. For a more traditional artisan, a painting or a house will last much longer than the average piece of code.&lt;/p&gt;

&lt;p&gt;You, me, even that guy at work who seems to be the fabled “10x engineer”, write transient code. Our code will not outlive us. Heck, the average lifespan of code written is between 6 months and 2 years. That is &lt;em&gt;nothing&lt;/em&gt; compared to other professions. What if civil engineers only had to make a bridge that lasted for 6 months? That would be one poorly built bridge that no one would want to drive over. But when writing software, that is often the expected life of the code. With that, it becomes quite clear that code written to not last a century should never be used to define a person’s life. If you had the desire to really define yourself by your code, you would probably spend 10 years writing and perfecting every single component. This is not feasible nor realistic. We are not building bridges to last decades upon decades, neither are we creating pieces of art to hang in museums for generations. We are building software to last “long enough”. We build it because we love to and because someone is most likely paying us to do it &lt;em&gt;(I still smile sometimes when I realize I get &lt;strong&gt;paid&lt;/strong&gt; to write code)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At the end of the day, everyone wants to be proud of the job they have done and the things they have achieved. People who write software are very lucky. We get to go home every day having created something new or made something better. However, we must remain humble. Humility will be our saving grace. It will be the thing that prevents us from going gray at the age of 35. Letting go of the code that we write will help us keep that bottle of Glenlivet from diminishing at an expeditious pace. Our families will not have to wonder when we will return home because we let our code go. We can rest easy knowing “that new guy who uses tabs instead of spaces” will be taking over the code we wrote a month ago, and that is &lt;strong&gt;ok&lt;/strong&gt;. Because in the end, the code we write will most likely be deleted within a year of its conception.&lt;/p&gt;

&lt;p&gt;You are not your code. You love to write code but are not defined by it. The code we write enriches our lives. We learn a great deal from the problems that we solve, but we are not defined by the solutions. I am a Software Artisan who’s code will be forgotten along with everyone else’s. I am happy I got to write it at all.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Short Feedback Cycles</title>
   <link href="https://jakeyesbeck.com/2015/06/07/short-feedback-cycles/"/>
   <updated>2015-06-07T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/06/07/short-feedback-cycles</id>
   <content type="html">&lt;p&gt;Forty-two days into my &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;year of commits&lt;/a&gt; initiative has come and gone. With it, I have found some great processes for making my contributions efficient and effective. Feedback is extremely important when writing software. After all, the code you write is probably designed to work, right? Right. A good way to verify correctness in your software is through automated tests. These can either be unit tests for specific methods and functions or integration tests; those that make sure a complete code path behaves as expected. Regardless, we write these tests to ensure our code works now and in the future. “In the future” is where I have started to contribute to projects.&lt;/p&gt;

&lt;p&gt;Good projects have test files that the original author(s) provide. Great projects have &lt;em&gt;fast&lt;/em&gt; test files that the original author(s) provide. Fast tests provide short feedback cycles. Short feedback cycles prevent bugs and help make new feature development and refactoring much more painless. Feedback governs our behaviors in and outside the development world. Without it, we would not be as efficient or effective at the tasks that are important to us. From writing software to training for a half marathon, feedback matters a great deal.&lt;/p&gt;

&lt;p&gt;In a recent &lt;a href=&quot;https://github.com/ariejan/imdb/pull/71&quot;&gt;contribution of mine&lt;/a&gt;, I relied heavily on automated testing and short feedback cycles. It was important to me that I was able to identify how the specs were changing as I upgraded them to RSpec 3. I used &lt;a href=&quot;https://github.com/guard/guard&quot;&gt;Guard&lt;/a&gt; to help run my tests automatically when any of the code changed. Guard is a tool to automatically run your automated test files as you are making changes to the code.&lt;/p&gt;

&lt;p&gt;Guard has been around for a long time. I chose to use it due to how simple it is to set up. All you need to do is include the &lt;code class=&quot;highlighter-rouge&quot;&gt;guard-rspec&lt;/code&gt; gem in your repository create a &lt;code class=&quot;highlighter-rouge&quot;&gt;Guardfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An example &lt;code class=&quot;highlighter-rouge&quot;&gt;Guardfile&lt;/code&gt; (which exists in the root of your repository) would look something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rspec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;cmd: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;rspec&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;notification: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{^spec/.+_spec&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;rb$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{^lib/(.+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;rb$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_spec.rb&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{^models/(.+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;rb$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/models/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_spec.rb&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;spec/spec_helper.rb&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Let’s break this file down and see exactly what is going on.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{^spec/.+_spec&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;rb$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This line tells Guard to watch each spec file and run the contained tests if the file has been saved. The file does not need to be changed, only saved for guard to run the specs.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{^lib/(.+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;rb$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_spec.rb&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{^models/(.+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;rb$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/models/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_spec.rb&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;These two lines do the same thing in different directories. The first looks in the &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; directory for anything ending in &lt;code class=&quot;highlighter-rouge&quot;&gt;.rb&lt;/code&gt; and runs the associated spec files in &lt;code class=&quot;highlighter-rouge&quot;&gt;spec/lib/&lt;/code&gt;. For example, if we have changed a file, &lt;code class=&quot;highlighter-rouge&quot;&gt;lib/foo.rb&lt;/code&gt;, then the spec, &lt;code class=&quot;highlighter-rouge&quot;&gt;spec/lib/foo_spec.rb&lt;/code&gt;, is run. The second line does the exact same thing for the &lt;code class=&quot;highlighter-rouge&quot;&gt;models&lt;/code&gt; directory.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;spec/spec_helper.rb&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This last line tells guard to run a specific directory (in this case, &lt;code class=&quot;highlighter-rouge&quot;&gt;spec&lt;/code&gt;) whenever our &lt;code class=&quot;highlighter-rouge&quot;&gt;spec/spec_helper.rb&lt;/code&gt; file is saved.&lt;/p&gt;

&lt;p&gt;With our &lt;code class=&quot;highlighter-rouge&quot;&gt;Guardfile&lt;/code&gt; set up, seeing the successes and failures of our test suite while we do development is as easy as running &lt;code class=&quot;highlighter-rouge&quot;&gt;guard&lt;/code&gt; in the root of our directory structure. Personally, I use &lt;code class=&quot;highlighter-rouge&quot;&gt;guard --clear&lt;/code&gt; to make the terminal clean up after itself between runs. This creates a nice blank slate to run each spec on and requires no additional scrolling.&lt;/p&gt;

&lt;p&gt;Guard has been a very valuable asset to me during my Year of Commits and it, or technologies in the same space, would be worth looking into for anyone searching for short feedback development. Go out there, keep your Guard up and make some great contributions to other people’s code!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Writing good API wrappers</title>
   <link href="https://jakeyesbeck.com/2015/05/31/wrapping-apis/"/>
   <updated>2015-05-31T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/05/31/wrapping-apis</id>
   <content type="html">&lt;p&gt;Both in my day job and in my &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;year of commits&lt;/a&gt;, I spend a lot of time thinking about APIs.&lt;/p&gt;

&lt;p&gt;For the uninitiated, an &lt;strong&gt;A&lt;/strong&gt;pplication &lt;strong&gt;P&lt;/strong&gt;rogram &lt;strong&gt;I&lt;/strong&gt;nterface (&lt;strong&gt;API&lt;/strong&gt;) is an avenue for one piece of software to speak to another. This could be a remote, web-based, HTTP API. Or, the API might be an internal interface for one portion of a software system to talk to another. Designing an API that is simple and maintainable is crucial if it is intended to be used and quickly adopted by colleagues or 3rd party developers.&lt;/p&gt;

&lt;p&gt;Being one of those 3rd party developers, I find myself using and writing wrappers to these APIs. Here, I will explain what makes a good API wrapper. Let’s postulate about some example wrapper designs.&lt;/p&gt;

&lt;h2 id=&quot;the-barely-abstractor&quot;&gt;The Barely Abstractor&lt;/h2&gt;

&lt;p&gt;The mantra of this design is: “I will take away that annoying HTTP element and you do literally all the rest.”&lt;/p&gt;

&lt;p&gt;We can assume that a library called &lt;code class=&quot;highlighter-rouge&quot;&gt;api_requester&lt;/code&gt; exists to wrap our very important 3rd party remote API (Which we will also assume is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Representational_state_transfer&quot;&gt;RESTful API&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If we wanted to retrieve an object our code might look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;api_requester&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;object_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;application/json&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;APIWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                  &lt;span class=&quot;s1&quot;&gt;&#39;relative/path/to/object/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; { big: :hash, of: :attributes}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To post an object via this wrapper:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;api_requester&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;object_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;object_name: :foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;object_type: :bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;object_description: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;I am an object&#39;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;application/json&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;APIWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&#39;relative/path/to/object/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; { big: :hash, of: :attributes}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So, you get the idea. That idea is verbosity. However, this approach is not all negative.&lt;/p&gt;

&lt;h3 id=&quot;pros&quot;&gt;Pros:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Resilient to API changes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;A big problem with wrapping APIs outside of your own control is endpoint churn, change, and deprecation. With such a verbose wrapper, the consumer is in complete control of the request. From URL changes to parameter addition and deletion, a consumer of `api_requester` is able to adapt without updating their library (just their own source code).
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Transparent&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Since `api_requester` does attempt to abstract out the intricacies of our 3rd party API, the consumer of `api_requester` knows exactly how the underlying API works. Understanding the nuances of the API being &quot;wrapped&quot; might influence the consumer&#39;s system architecture positively.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;cons&quot;&gt;Cons:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;No abstraction&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Without abstraction, a consumer of `api_requester` must be one with the 3rd party API&#39;s documentation. To ensure competent use, the consumer must become familiar with all possible endpoints and usage patterns. This nearly completely defeats the purpose of providing a wrapper.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Does not minimize 3rd party surface area&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;One of the main purposes of wrapping a 3rd party API is to minimize its overall surface area. Making small, distinct interaction points is important for the consumer of `api_requester`. Fewer moving pieces means fewer points of failure. It is probably not necessary for every single end point and function to be exposed by `api_requester`.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-over-abstraction-contraption&quot;&gt;The Over-abstraction contraption&lt;/h2&gt;

&lt;p&gt;Unlike our &lt;code class=&quot;highlighter-rouge&quot;&gt;api_requester&lt;/code&gt;, the mindset behind this pattern is: “Make sure no one can actually understand what is going on behind the scenes”.&lt;/p&gt;

&lt;p&gt;Wrapping the same RESTful 3rd party API, &lt;code class=&quot;highlighter-rouge&quot;&gt;api_contraption&lt;/code&gt;, will be our next library. Its code might be used in the following way:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;api_contraption&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;APIWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch_an_object&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;lt;Object @variable=:thing, @other_variable=:other_thing&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To post an object via this wrapper:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;api_contraption&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;APIWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch_an_object&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_object_attribute!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;lt;Object @variable=:updated, @other_variable=:also_magically_updated&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As demonstrated, this library is nearly 100% magic. &lt;code class=&quot;highlighter-rouge&quot;&gt;APIWrapper&lt;/code&gt; exposes arbitrary methods like &lt;code class=&quot;highlighter-rouge&quot;&gt;fetch_an_object&lt;/code&gt; and returns a magical object with instance variables set.&lt;/p&gt;

&lt;h3 id=&quot;pros-1&quot;&gt;Pros:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Actual abstraction&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Consumers of `api_contraption` do not need to understand the underlying API&#39;s full functionality. The wrapper has provided (hopefully) a small handful of useful methods and classes to expose the heart of the API it wraps.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;cons-1&quot;&gt;Cons:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Inflexible&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Whenever the underlying API needs to change a response or request contract, the `api_contraption` has to change. This can be a very tiring exercise for its consumers. However, if the API being wrapped is very stable, this inflexibility might not be noticed as greatly.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Makes the underlying API a black box&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;While the `api_requester` above did not do enough abstraction, this `api_contraption` does too much. It prevents developers from discovering useful features of the 3rd party API that might be helpful to them. Granted, a consumer could refer to the service&#39;s own documentation for feature discovery but who says that they should be forced to?
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;so-which-is-better&quot;&gt;So which is better?&lt;/h2&gt;

&lt;p&gt;The answer is neither. A desirable solution exists somewhere between these two examples. An API wrapper should be terse yet flexible, simple yet sophisticated. Making a consumer of your wrapper upgrade with every API change is not scalable and will drive people away from it. At the same time, if a consumer cannot see the value your library gives them, why would they bother to use it?&lt;/p&gt;

&lt;p&gt;A good abstraction, a positive value add piece of software can be defined by a few key features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Flexibility&lt;/li&gt;
  &lt;li&gt;Usefulness&lt;/li&gt;
  &lt;li&gt;Readability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of our example libraries had one or two of these features but not all three. To make up for what was lacking let’s try and make a hybrid of the two: an &lt;code class=&quot;highlighter-rouge&quot;&gt;api_wrapper&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-middle-ground&quot;&gt;The middle ground&lt;/h2&gt;

&lt;p&gt;Requesting an Object&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;api_wrapper&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;APIWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DesiredObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &amp;lt;DesiredObject @id=123, @name=&#39;The One&#39;, @author=&#39;The Architect&#39;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Updating an object&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;api_wrapper&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;APIWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DesiredObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;object_wanted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;author: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Mr. Smith&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &amp;lt;DesiredObject @id=123, @name=&#39;The One&#39;, @author=&#39;Mr. Smith&#39;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;At first glance it might not seem like all too much is different between this solution and the previous two. However, a few key differences are present.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;We no longer have a generic superclass &lt;code class=&quot;highlighter-rouge&quot;&gt;APIWrapper&lt;/code&gt; to interact with, it has become a namespace. With this namespace, clients can freely inherit their own objects from our &lt;code class=&quot;highlighter-rouge&quot;&gt;DesiredObject&lt;/code&gt; class and make modifications as they see fit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Abstraction is still very much in play. URL structures, HTTP payloads and other small minutia about the request is abstracted away from our consumers and they are given very logical methods &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;update&lt;/code&gt;. These methods enable our consumer to interact with their resources in a familiar and pleasant way.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am not saying this solution is perfect, but it is objectively better than the other two. A lot of factors go into making a great API wrapper. Adhering to the three ideal attributes: &lt;strong&gt;Flexibility&lt;/strong&gt;, &lt;strong&gt;Usefulness&lt;/strong&gt; and &lt;strong&gt;Readability&lt;/strong&gt; will at least point your projects in the right direction.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Contributing</title>
   <link href="https://jakeyesbeck.com/2015/05/24/finding-projects/"/>
   <updated>2015-05-24T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/05/24/finding-projects</id>
   <content type="html">&lt;p&gt;Since starting this 365 day adventure, I have done a mixture of contributing to my own projects and to others. At the on-set, I made an assumption that it would be an even distribution of commits between my own projects and existing ones. However, this proved much harder than I originally thought. After a sizable amount of effort, I did find a few projects to contribute to. 28 days into this endeavor and seems like I might actually be able to accomplish my goal.&lt;/p&gt;

&lt;p&gt;One of the existing projects, &lt;a href=&quot;https://github.com/girishso/pluck_to_hash&quot;&gt;pluck to hash&lt;/a&gt;, was a very young project when I found it. The project was released without any test coverage so I attempted to &lt;a href=&quot;https://github.com/girishso/pluck_to_hash/pull/6&quot;&gt;rectify that&lt;/a&gt;. Thankfully my pull request was accepted! It felt great to finally contribute to a project that wasn’t my own. I also learned a few things by doing so.&lt;/p&gt;

&lt;p&gt;The first important learning from making a contribution was understanding that the caliber of contributors to open source software was not vastly superior to “normal” software engineers. I had previously thought of people who wrote open source libraries to be some sort of battle-tested, hardened, bug-resistant demi-gods sent here from Krypton in order to write code for us mortals. This was a very debilitating thought. For years it was a wall between me and open source software development. I didn’t even entertain the idea of surpassing that wall and inevitably gave up on making meaningful contributions. Alright, that is probably a little dramatic but I think it makes my point for me. It was intimidating to contribute! Then, like a breath of fresh air, my pull request was accepted and these preconceptions vanished. It was awesome. It was super awesome (and objectively I didn’t even do that much).&lt;/p&gt;

&lt;p&gt;A second learning from finding projects to contribute to was how to find them. It seems like an important thing to know, right? There are a few tools one can use to find projects that are ripe for the commit-in. Using the &lt;a href=&quot;https://github.com/trending&quot;&gt;explore function on Github&lt;/a&gt;, you can find the top trending projects on a per language basis. This process is how I found the puck to hash gem and decided to contribute. A big difference between the pluck to hash repository and others is the fact that pluck to hash did not have any open issues. Contributing to a repository with no open issues could be considered risky. After all, if a project has open issues then at least some work is welcome and expected. A project with no open issues can not be assumed to want, need, or accept contributions. Luckily for me, the pluck to hash maintainer was open to my additions.&lt;/p&gt;

&lt;p&gt;A great resource for finding projects ordered by issue count is &lt;a href=&quot;https://www.codetriage.com/&quot;&gt;CodeTriage&lt;/a&gt;. CodeTriage does a great job of indexing projects hosted on Github in descending order of their open issues. Finding the right projects to contribute to is hard, but with CodeTriage and the built in issue trackers in Github, contributing to repositories that matter to you and to others is achievable.&lt;/p&gt;

&lt;p&gt;Use these resources and start making some contributions of your own.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Just learn Rails</title>
   <link href="https://jakeyesbeck.com/2015/05/17/just-learn-rails/"/>
   <updated>2015-05-17T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/05/17/just-learn-rails</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Obligatory YoC update: Still going strong, 21 days in a row!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The only real city I have lived in is San Francisco. I assume that in other cities, like New York and Los Angeles, people bring up topics relevant to industries popular there. So I would imagine that in New York, a person could overhear something about: banking, stock trading, fashion, and expensive brunches. While in Los Angeles, you might wander by people having conversations pertaining to: making movies and working at the Cheesecake Factory. I have come to this conclusion because everyone in San Francisco talks about writing software.&lt;/p&gt;

&lt;p&gt;I personally love hearing conversations about software as often as I do &lt;em&gt;(I did move to San Francisco for the purpose of writing it)&lt;/em&gt;. One theme that seems to pop up often is how people can get into writing software for themselves. This is great, more people in the space means more ideas and more innovation. However, some people seem to be under the impression that breaking into software development (specifically web development) is as simple as “just learning Rails”. I hope to explain why that mentality is a little naive.&lt;/p&gt;

&lt;p&gt;So what’s the problem with just learning Ruby on Rails? You &lt;strong&gt;might&lt;/strong&gt; be able to pick up software development through learning a framework and even get a job that will pay you real money. However, I sincerely doubt that it will be a pleasant experience for long. Frameworks are a single tool a person can use to correctly and efficiently do their job.&lt;/p&gt;

&lt;p&gt;I would wager that everyone is familiar with the type of work that a carpenter might do, but just for laughs, I’ll give you an example. A carpenter could be contracted to build a wooden table and chairs for a client. He would shape the wood, sand, treat, stain and polish it until the dining set was made. I highly doubt he would be able to do all that with just a single tool. Can you imagine the quality of his product if he only used a chisel? This is a bit of a stretch but I feel it portrays the point I am trying to make. Artisans need multiple tools to do their jobs effectively and efficiently (&lt;em&gt;fyi: if you don’t call yourself a software artisan then you are missing a great branding opportunity&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;In the same way that a chisel is not enough for the carpenter, a framework is not enough for our software artisan. The beauty of frameworks like Ruby on Rails is that they can get you into making a product quickly. But, as soon as you hit any kind of interesting problems, you’ll have to rely on something else. It might even be something that your framework has abstracted from you and discouraged you from learning for yourself.&lt;/p&gt;

&lt;p&gt;For instance, Rails ships with a custom ORM: &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt;. This reasonably straight forward library makes interacting with your database simple enough to start persisting objects. Great! What happens when you start persisting large amount of objects? What happens when the relationships that you have created between these objects start to cause performance losses? Your users get mad. Not great. They get so mad they don’t even know why they are using your product and they bounce. To remedy this problem, you would have to tweak your database indexes in a way that speeds up your queries for you. You’d have to know how a relational database works, how indexes work and when to use the proper ones. If you would be using postgres, it would be imperative that you understand what &lt;code class=&quot;highlighter-rouge&quot;&gt;explain analyze&lt;/code&gt; can tell you. As you traverse down this path of improving your product you will be outside of the framework and thus without your only tool.&lt;/p&gt;

&lt;p&gt;While this is just one example, I think it makes my point relatively well. We could spend page after page of other examples not given to you by your framework: JavaScript, Redis, Memcache, CSS, Git, a variety of Linux commands dealing with debugging and server maintenance, etc. And even after all of that, after you learn everything about those technologies and can make web software that scales, there are other aspects of software development. Like being on a team that either does agile, waterfall or quick stream methodology. Or how to deal with merge conflicts on a complex system, architectural design decisions, 2 spaces vs 4 &lt;em&gt;(spoiler: its always 2)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The point of this post is not to discourage, I want to simply educate. Learning new tools and technologies is important and a ton of a fun! Just make sure that when you have to get our your toolbox you have more than just a chisel in there. Challenge yourselves to look outside the framework. Figure out what your frameworks are doing for you and learn why someone built it to do those things. Understanding the underlying technologies a framework utilizes is key to your success and to the community’s.&lt;/p&gt;

&lt;p&gt;I look forward to seeing what all you software artisans build.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>validates_type</title>
   <link href="https://jakeyesbeck.com/2015/05/10/validates-type/"/>
   <updated>2015-05-10T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/05/10/validates-type</id>
   <content type="html">&lt;p&gt;In keeping with my apparent obsession with types, I created another &lt;em&gt;helpful&lt;/em&gt; library: &lt;a href=&quot;https://github.com/yez/validates_type&quot;&gt;validates_type&lt;/a&gt;. I wanted a nice, lightweight way to assert that the types of my attributes are exactly what I need them to be once I save them to the database.&lt;/p&gt;

&lt;p&gt;No one is particularly fond of littering their code with &lt;code class=&quot;highlighter-rouge&quot;&gt;try&lt;/code&gt;s and &lt;code class=&quot;highlighter-rouge&quot;&gt;is_a?&lt;/code&gt;s. To remedy this, I make my models assert confidence that the data in my database is what I expect. I’m not talking about type coercion, type casting or any other munging of types that might happen on a typical read/write from your handy dandy ORM of choice. No no, this is the real deal, the bees knees, the elbows of a gazelle: &lt;strong&gt;actual type validation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Data quality is important to me, and should be important to you too. This library is an attempt at injecting some structure into your typical Rails/Sinatra app in order to keep your data clean and your system happy.&lt;/p&gt;

&lt;h4 id=&quot;alright-so-when-would-this-kind-of-thing-be-necessary-lets-see-an-example-of-how-automagic-type-coercion-can-bite-us&quot;&gt;Alright so when would this kind of thing be necessary? Let’s see an example of how automagic type coercion can bite us.&lt;/h4&gt;

&lt;p&gt;Let’s say you’re using Rails, and let’s pretend for a moment that for some reason, you have some code that looks like this:&lt;/p&gt;

&lt;p&gt;A very important class:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ImportantResource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Attribute named :settings with what we want to be an array&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# of important things encoded and stored in either&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# a nice postres json column or a text column&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;store_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:array_of_things&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And a matching very important controller:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ImportantResourceController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ImportantResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# let&#39;s set the array_of_things to a parameter that is passed in&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#  via a form or something&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;array_of_things&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:array_of_things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# great, lets save that resource&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# cool everything worked, this could not have gone better&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h4 id=&quot;oh-no-george-what-about-if-something-other-than-array-is-passed-to-that-parameter&quot;&gt;Oh no, george! What about if something other than array is passed to that parameter??&lt;/h4&gt;

&lt;p&gt;Well let’s see what might happen. If &lt;code class=&quot;highlighter-rouge&quot;&gt;params[:array_of_things] = &#39;a random string&#39;&lt;/code&gt;, any other method or object that needs to interact with &lt;code class=&quot;highlighter-rouge&quot;&gt;ImportantResource&lt;/code&gt; would have a bad time unless they explictly validated &lt;code class=&quot;highlighter-rouge&quot;&gt;array_of_things&lt;/code&gt; is an array. We don’t have any ORM coercion to fall back on here since this is a &lt;code class=&quot;highlighter-rouge&quot;&gt;store_accessor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wouldn’t it be nicer to have &lt;code class=&quot;highlighter-rouge&quot;&gt;ImportantResource&lt;/code&gt; validate itself so no other object needs to care about &lt;code class=&quot;highlighter-rouge&quot;&gt;array_of_things&lt;/code&gt;’s array-ness?&lt;/p&gt;

&lt;p&gt;This sounds awesome to me, and I agree. Let’s check it out and how you can harness the power for yourself. What if instead of letting &lt;code class=&quot;highlighter-rouge&quot;&gt;ImportantResource&lt;/code&gt; behave in any which way, we locked that thing down? It might look something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ImportantResource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Attribute named :settings with what we want to be an array&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# of important things encoded and stored in either&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# a nice postres json column or a text column&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;store_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:array_of_things&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;validates_type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:array_of_things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:array&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now if we try to save any other value to &lt;code class=&quot;highlighter-rouge&quot;&gt;array_of_things&lt;/code&gt; that isn’t an array, we receive validation errors added to &lt;code class=&quot;highlighter-rouge&quot;&gt;important_resource.errors&lt;/code&gt; in the same way other ActiveRecord/ActiveModel classes behave! This will keep us honest with what we set our data to.&lt;/p&gt;

&lt;h4 id=&quot;so-why-use-this-pattern-at-all-some-of-my-data-might-be-the-wrong-type-but-who-cares&quot;&gt;So why use this pattern at all? Some of my data might be the wrong type but who cares?&lt;/h4&gt;

&lt;p&gt;I think you should care, I sure as heck do. For instance, what if the software we’re writing is an API that people &lt;strong&gt;need&lt;/strong&gt; to use? Wouldn’t you rather them be confident that your documentation (that you painstakingly wrote for hours) is correct?&lt;/p&gt;

&lt;p&gt;For example, lets say you build a medical API: &lt;code class=&quot;highlighter-rouge&quot;&gt;SuperImportantMedicalAPI&lt;/code&gt;. And in a super important response about a patient, a boolean value is returned for &lt;code class=&quot;highlighter-rouge&quot;&gt;patient_is_allergic_to_nuts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This totally legitimate example shows how imperative it is that &lt;code class=&quot;highlighter-rouge&quot;&gt;SuperImportantMedicalAPI&lt;/code&gt;’s types be locked down. If people are depending on your awesome API to save them from nut allergies, don’t let a string like &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;t&#39;&lt;/code&gt; be your downfall. The people need &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; and can handle &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;, give them what they want.&lt;/p&gt;

&lt;h4 id=&quot;great-great-heres-some-faqs&quot;&gt;Great? Great! Here’s some FAQs:&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Do the validations behave exactly the same as &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel::Validations&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; Exactly the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; So does that mean I can chain other validations on?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; Heck yes, check it out:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# custom messaging for errors&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;validates_type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:array_of_things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;message: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;This needs to be an array!!!&#39;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# chaining on other validation like numericality&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;validates&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:other_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;type: :integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;ss&quot;&gt;numericality: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;greater_than: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# making sure object is a string and included in a specific list&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;validates&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:yet_another_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;type: :string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;ss&quot;&gt;inclusion: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;in: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;foo&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Can I use this with &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; &lt;strong&gt;or&lt;/strong&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; Y to the es! Yes! Isn’t that cool? Any ruby code that uses either &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveModel&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; can use all the power of this gem on day&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Does this cost at least $1,000 every time I need to use it?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; Close, you can use this library right now for the low low price of $0. I tried to make it lower but just couldn’t do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Where can I read more?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; &lt;a href=&quot;https://github.com/yez/validates_type&quot;&gt;Right freakin’ here&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Boolean</title>
   <link href="https://jakeyesbeck.com/2015/05/03/ruby-boolean/"/>
   <updated>2015-05-03T08:00:00-04:00</updated>
   <id>https://jakeyesbeck.com/2015/05/03/ruby-boolean</id>
   <content type="html">&lt;p&gt;Week one of my &lt;a href=&quot;https://jakeyesbeck.com/2015/04/23/a-year-of-commits/&quot;&gt;Year of Commits&lt;/a&gt; initiative is complete, 51 more to go. I did not plan on telling people about this until a few weeks into the task (in case history repeated itself and I gave up 20% in). But that didn’t happen; people found out about it almost immediately, demonstrating yet again just how easy it is to find anything on the Internet. Thanks, Obama.&lt;/p&gt;

&lt;p&gt;So what happened in the first week? Did I change the world of open source forever? Did I contribute a monumental change to one of the most well renown ruby libraries out there? Nope, I made a gem that at its core is 3 lines long. I made a &lt;a href=&quot;https://github.com/yez/ruby-boolean&quot;&gt;boolean gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I can see that most people would wonder: “Why?”, “Why did he make this useless thing? Doesn’t he know that ruby does not have the boolean type &lt;a href=&quot;https://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/96356&quot;&gt;by design&lt;/a&gt;?”. The answer is simple. I found myself over and over again typing some kind of nonsense like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# For some reason we need to know if this value&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# is a boolean or not&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# @boolean?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   param: value - what we want to know is a boolean or not&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   return: true/false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;boolean?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TrueClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FalseClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This, however, could also be questioned. “Who cares if something is a boolean or not? This is ruby, duck-type that shiz”. Sure, that makes sense, I can do that. But do I want to do that? No. Why not? Because sometimes knowing the type of something can be important. You might not always have a background process like ActiveRecord’s type coercion to clean up your types for you. Or maybe you actually want something to be a boolean, not &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;t&#39;&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;&#39;f&#39;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This gem is not alone. Other gems that do similar and much more functionality exist as well (i.e. &lt;a href=&quot;https://rubygems.org/gems/bool/versions/1.0.20&quot;&gt;bool&lt;/a&gt; and &lt;a href=&quot;https://github.com/RISCfuture/boolean&quot;&gt;boolean&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;With the &lt;a href=&quot;https://github.com/yez/ruby-boolean&quot;&gt;ruby-boolean gem&lt;/a&gt;, the same kind of code can be re-written:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Super important business logic method&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;some_method_where_booleans_matter&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Do boolean related stuff&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Throw a fit about it not being a boolean&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Great! Now I only have to check one class instead of two. My life is now perfect, what could possibly make this any better? Nothing.&lt;/p&gt;

&lt;p&gt;This project was a fun introduction to the 365 commit-a-thon I am embarking on. Maybe someone will even use it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A Year of Commits</title>
   <link href="https://jakeyesbeck.com/2015/04/23/a-year-of-commits/"/>
   <updated>2015-04-23T09:15:09-04:00</updated>
   <id>https://jakeyesbeck.com/2015/04/23/a-year-of-commits</id>
   <content type="html">&lt;p&gt;Some people have no problem being motivated to be excellent every single day. I am not one of those people. While I love what I do, I think I can do better. It is very easy to make excuses for why I have countless side projects around 20% completion. Maybe people believe me when I say “I just don’t have time right now.” or “I’ve just been slammed at work.”. Those excuses are bullshit. There are plenty of people with way more on their plate than I. That is why I want to embark on a new adventure – “A Year of Commits”.&lt;/p&gt;

&lt;p&gt;For the next year, I will make at least 1 commit per day to a &lt;strong&gt;public&lt;/strong&gt; repository on github. I am counting the commits by the day they are made, not they day they are merged in (in cases of public PRs).&lt;/p&gt;

&lt;p&gt;Additionally, I will make 1 blog post per week. That’s 52 blog posts total counting this one (in case for some reason you don’t know how many weeks are in a year or whatever). It’s my first blog so who knows what will happen. Do people put pictures in blogs?&lt;/p&gt;

&lt;p&gt;So who cares? Why would I go through the trouble of making this blog to exist alongside the gazillion other ones out there? Because I want to. I think it will be not only a great motivator for me but potentially provide some comic relief to any wandering interneters that happen to stumble upon this.&lt;/p&gt;
</content>
 </entry>
 

</feed>
