<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Crafting Ruby</title>
    <description>A Ruby on Rails blog covering RoR features and solutions to uncommon problems.
</description>
    <link>https://craftingruby.com/</link>
    <atom:link href="https://craftingruby.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Sun, 20 Aug 2023 10:42:51 +0000</pubDate>
    <lastBuildDate>Sun, 20 Aug 2023 10:42:51 +0000</lastBuildDate>
    
      <item>
        <title>I'm not testing those stupid views!</title>
        <description>&lt;p&gt;Over the course of a Rails project, views that started out very simple can evolve into a complex mix of HTML with complicated nested Ruby conditionals. They become hard to understand, hard to read and hard to work with. Fixing an edge case in those views may involve the painstaking process of writing of an end-to-end test to ensure the bug has been squashed. Those kind of tests have quite an impact on the overall runtime of the test suite, so typically you don’t want to write too many of them. Especially not for edge cases. The more end-to-end tests you have, the harder it becomes to make changes to your views because the tests have all kinds of expectations of them.&lt;/p&gt;

&lt;p&gt;Keeping views as stupid as possible is important. The complicated logic in views is hard to test because you need to think a lot about things like HTML, clicking buttons and CSS selectors.&lt;/p&gt;

&lt;p&gt;A simple solution to the problem is to move the logic into separate classes. Logic in separate classes can easily be unit tested. Unit tests run fast and are the cheapest kind of tests to write.&lt;/p&gt;

&lt;p&gt;Consider this contrived example of a view with a bit of complex logic:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;checkout&quot;&amp;gt;
  &amp;lt;% if @order.line_items.count &amp;gt; 0 %&amp;gt;
    &amp;lt;% if (@order.total - @order.paid) &amp;gt; 0 %&amp;gt;
      &amp;lt;div class=&quot;outstanding-amount&quot;&amp;gt;&amp;lt;%= number_to_currency(@order.total - @order.paid) %&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;% end %&amp;gt;
    &amp;lt;div class=&quot;all-the-line-items&quot;&amp;gt;&amp;lt;/div&amp;gt;

    &amp;lt;% if @order.cancelled_at.nil? &amp;amp;&amp;amp; (@order.total - @order.paid) &amp;gt; 0 %&amp;gt;
      &amp;lt;%= link_to &quot;Cancel your order&quot;, cancel_order_path(@order) %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;% else %&amp;gt;
    Your order is empty!
  &amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You need to think in order to understand what’s going on here. Especially that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; condition may keep you occupied for a while.&lt;/p&gt;

&lt;p&gt;In Rails projects the obvious candidates to move the logic to are the view decorators. Try to move only the logic and keep HTML rendering out of the decorators as much as possible. Writing tests for rendered HTML is a lot harder than writing a test for a simple return value.&lt;/p&gt;

&lt;p&gt;One decorator doesn’t necessarily need to be the container for all the logic. You can create a decorator for only a single page or a specific section of the page. A decorator can also delegate the logic to other classes that aren’t decorators. I’ve written more about splitting up decorators in &lt;a href=&quot;/posts/2015/12/09/rails-antipattern-fat-decorator.html&quot;&gt;Rails Anti-Pattern: Fat Decorator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the above view, such a decorator may look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class OrderDecorator &amp;lt; Draper::Decorator
  delegate_all

  def checkout_possible?
    line_items.count &amp;gt; 0
  end

  def can_be_cancelled?
    cancelled_at.nil? &amp;amp;&amp;amp; !complete?
  end

  def complete?
    unpaid == 0
  end

  def unpaid
    total - paid
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the logic has been extracted into a decorator, the view became more pleasant to read:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;checkout&quot;&amp;gt;
  &amp;lt;% if @order.checkout_possible? %&amp;gt;
    &amp;lt;% unless @order.complete? %&amp;gt;
      &amp;lt;div class=&quot;outstanding-amount&quot;&amp;gt;$ &amp;lt;%= number_to_currency(@order.unpaid) %&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;% end %&amp;gt;
    &amp;lt;div class=&quot;all-the-line-items&quot;&amp;gt;&amp;lt;/div&amp;gt;

    &amp;lt;% if @order.can_be_cancelled? %&amp;gt;
      &amp;lt;%= link_to &quot;Cancel your order&quot;, cancel_order_path(@order) %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;% else %&amp;gt;
    Your order is empty!
  &amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the views become completely obvious there’s hardly a need to test any edge cases. Mistakes can be caught just as good by the naked eye rather. Time is saved by writing simple tests rather than complicated end-to-end tests. The test suite runs faster so your TDD cycle is hardly slowed down. Keeping your views stupid saves you some energy because you don’t have to be vigilant all the time.&lt;/p&gt;
</description>
        <pubDate>Tue, 25 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://craftingruby.com/posts/2016/10/25/im-not-testing-those-stupid-views.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2016/10/25/im-not-testing-those-stupid-views.html</guid>
        
        
      </item>
    
      <item>
        <title>Cleaner RSpec examples and failure messages</title>
        <description>&lt;p&gt;RSpec offers an extensive, flexible DSL to write your tests. But due to its extensive arsenal of matchers, RSpec requires some more effort to use properly than some other testing frameworks like Minitest.&lt;/p&gt;

&lt;p&gt;Have a look at the following spec:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
RSpec.describe ShoppingCart, type: :model do
  let(:shopping_cart) { subject }

  describe '#to_order' do
    let(:product1) { create(:product, price: 10) }
    let(:product2) { create(:product, price: 3) }
    let(:user) { create(:user) }

    before do
      shopping_cart.insert(product1, quantity: 2)
      shopping_cart.insert(product2)
    end

    it 'has the correct attributes' do
      order = shopping_cart.to_order(user)

      expect(order.price).to eq(23)
      expect(order.user).to eq(user)
    end

    it 'adds the products to the order' do
      line_items = shopping_cart.to_order(user).line_items

      expect(line_items[0].product).to eq(product1)
      expect(line_items[0].quantity).to eq(2)
      expect(line_items[1].product).to eq(product2)
      expect(line_items[1].quantity).to eq(1)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It kind of gets the job done, but it’s not super easy to read. It doesn’t really feel like the RSpec way of doing it, especially not with those local variable assignments. Lastly, it forces a specific sorting order of line items in the last example. I’m absolutely not a fan of enforcing unnecessary implementation details as a side-effect.&lt;/p&gt;

&lt;h2 id=&quot;built-in-matchers&quot;&gt;Built-in matchers&lt;/h2&gt;
&lt;p&gt;RSpec comes with a whole bunch of built-in matchers for your expectations. Its documentation extensively describes the &lt;a href=&quot;https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers&quot;&gt;built-in matchers&lt;/a&gt; and &lt;a href=&quot;https://relishapp.com/rspec/rspec-mocks/docs/setting-constraints/matching-arguments&quot;&gt;argument matchers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These matchers can be used in a lot of different situations. One that would come in handy here is &lt;a href=&quot;https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/have-attributes-matcher&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;have_attributes&lt;/code&gt;&lt;/a&gt; and its alias &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;an_object_having_attributes&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
RSpec.describe ShoppingCart, type: :model do
  let(:shopping_cart) { subject }

  describe '#to_order' do
    let(:product1) { create(:product, price: 10) }
    let(:product2) { create(:product, price: 3) }
    let(:user) { create(:user) }

    before do
      shopping_cart.insert(product1, quantity: 2)
      shopping_cart.insert(product2)
    end

    it 'has the correct attributes' do
      expect(shopping_cart.to_order(user))
        .to have_attributes(price: 23, user: user)
    end

    it 'adds the products to the order' do
      expect(shopping_cart.to_order(user).line_items).to contain_exactly(
        an_object_having_attributes(product: product1, quantity: 2),
        an_object_having_attributes(product: product2, quantity: 1)
      )
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the sort order of the line items became irrelevant thanks to &lt;a href=&quot;https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/contain-exactly-matcher&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contain_exactly&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using the appropriate matchers can make a spec almost read like human language. There’s not really a lot of logic involved that needs to be understood to figure out what the examples do.&lt;/p&gt;

&lt;p&gt;Another nice resource is &lt;a href=&quot;https://gist.github.com/JunichiIto/f603d3fbfcf99b914f86&quot;&gt;this list of available matchers in RSpec 3 and their aliases&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;cleaner-failure-messages&quot;&gt;Cleaner failure messages&lt;/h2&gt;
&lt;p&gt;A great disadvantage of using a matcher like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;have_attributes&lt;/code&gt; is that combined with ActiveRecord objects, it can easily fill your whole screen with a single failure message, printing out only a few objects:&lt;/p&gt;

&lt;pre&gt;
Failures:

1) ShoppingCart#to_order adds the products to the order
   Failure/Error: expect(shopping_cart.to_order(user).line_items).to contain_exactly(
     expected collection contained:  [(an object having attributes {:product =&amp;gt; #&amp;lt;Product id: 1, name: &quot;Product #3&quot;, price: 10, created_at: &quot;2015-12-14 22:42:05&quot;, updated_at: &quot;2015-12-14 22:42:05&quot;&amp;gt;, :quantity =&amp;gt; 2}), (an object having attributes {:product =&amp;gt; #&amp;lt;Product id: 2, name: &quot;Product #4&quot;, price: 3, created_at: &quot;2015-12-14 22:42:05&quot;, updated_at: &quot;2015-12-14 22:42:05&quot;&amp;gt;, :quantity =&amp;gt; 1})]
     actual collection contained:    [#&amp;lt;LineItem id: 1, product_id: 1, order_id: 1, quantity: 1, created_at: &quot;2015-12-14 22:42:05&quot;, updated_at: &quot;2015-12-14 22:42:05&quot;&amp;gt;, #&amp;lt;LineItem id: 2, product_id: 2, order_id: 1, quantity: 1, created_at: &quot;2015-12-14 22:42:05&quot;, updated_at: &quot;2015-12-14 22:42:05&quot;&amp;gt;]
     the missing elements were:      [(an object having attributes {:product =&amp;gt; #&amp;lt;Product id: 1, name: &quot;Product #3&quot;, price: 10, created_at: &quot;2015-12-14 22:42:05&quot;, updated_at: &quot;2015-12-14 22:42:05&quot;&amp;gt;, :quantity =&amp;gt; 2})]
     the extra elements were:        [#&amp;lt;LineItem id: 1, product_id: 1, order_id: 1, quantity: 1, created_at: &quot;2015-12-14 22:42:05&quot;, updated_at: &quot;2015-12-14 22:42:05&quot;&amp;gt;]
   # ./spec/models/shopping_cart_spec.rb:22:in `block (3 levels) in &amp;lt;top (required)&amp;gt;'
&lt;/pre&gt;

&lt;p&gt;This kind of spam is ridiculous. Most of this information we don’t care about, and it’s only distracting from what does matter.&lt;/p&gt;

&lt;p&gt;One option would be to modify the objects being checked in a way to produce simpler failure messages, such as below:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
it 'adds the products to the order' do
  line_items = shopping_cart.to_order(user).line_items.map do |item|
    item.slice(:product, :quantity)
  end

  expect(line_items).to contain_exactly(
    { 'product' =&amp;gt; product1, 'quantity' =&amp;gt; 2 },
    { 'product' =&amp;gt; product2, 'quantity' =&amp;gt; 1 }
  )
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m not a fan of this approach at all. It simplifies the failure message, but it complicates the spec by adding logic. Every time you read the spec, you need to wade through this logic to understand the examples.&lt;/p&gt;

&lt;p&gt;It’s actually quite easy to customize the way objects are being printed without having to compromise conciseness of the specs. Simply by overriding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inspect&lt;/code&gt; method you can alter the output of objects in a failure message:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class LineItem &amp;lt; ActiveRecord::Base
  belongs_to :product
  belongs_to :order

  def inspect
    &quot;#{quantity} x #{product.inspect}&quot;
  end
end

class Product &amp;lt; ActiveRecord::Base
  def inspect
    name
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the irrelevant noise removed the failure message now becomes readable:&lt;/p&gt;

&lt;pre&gt;
Failures:

1) ShoppingCart#to_order adds the products to the order
 Failure/Error: expect(shopping_cart.to_order(user).line_items).to contain_exactly(
   expected collection contained:  [(an object having attributes {:product =&amp;gt; Product #3, :quantity =&amp;gt; 2}), (an object having attributes {:product =&amp;gt; Product #4, :quantity =&amp;gt; 1})]
   actual collection contained:    [1 x Product #3, 1 x Product #4]
   the missing elements were:      [(an object having attributes {:product =&amp;gt; Product #3, :quantity =&amp;gt; 2})]
   the extra elements were:        [1 x Product #3]
 # ./spec/models/shopping_cart_spec.rb:22:in `block (3 levels) in &amp;lt;top (required)&amp;gt;'
 &lt;/pre&gt;

&lt;p&gt;If you rely heavily on inspecting objects using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pp&lt;/code&gt;, this approach might not be convenient since it will overwrite the pretty print output with the custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inspect&lt;/code&gt; output. For custom objects, you can easily override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pretty_print&lt;/code&gt; to have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pp&lt;/code&gt; print a more detailed output if you need it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class SomeObject
  def inspect
    'Test'
  end

  def pretty_print(pp)
    pp.pp_object(self)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For ActiveRecord objects however, this doesn’t produce great output. There’s not really a nice way around it, the best I found is to override a private method to have ActiveRecord print out the useful output it did before:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class SomeObject &amp;lt; ActiveRecord::Base
  def inspect
    'Test'
  end

  private

  def custom_inspect_method_defined?
    false
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Being more aware of the matchers RSpec offers, it allows you to write clean, concise and elegant examples. It’s worth taking a moment to browse the available matchers from time to time. After writing an example, take a step back and wonder if there’s a better way to write it. After some time you become aware of a lot more possibilities write cleaner specs, and thus reduce their complexity.&lt;/p&gt;

&lt;p&gt;The full source project for the code above can be found &lt;a href=&quot;https://github.com/fivedigit/rspec_matchers&quot;&gt;on this Github repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What are your favourite RSpec matchers? Let me know in the comments down below!&lt;/p&gt;
</description>
        <pubDate>Tue, 15 Dec 2015 07:20:00 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/12/15/cleaner-rspec-examples-and-failure-messages.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/12/15/cleaner-rspec-examples-and-failure-messages.html</guid>
        
        
      </item>
    
      <item>
        <title>Rails Anti-Pattern: Fat Decorator</title>
        <description>&lt;p&gt;Using decorators in Ruby on Rails has many benefits. Models become less fat, views less complicated, and using the procedural view helpers becomes a thing of the past.&lt;/p&gt;

&lt;p&gt;When applying decorators to your Rails project, you might be tempted to maintain a 1:1 mapping between models and decorators. All the presentation logic of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Article&lt;/code&gt; would go into an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArticleDecorator&lt;/code&gt;. While the decorators are small, this may be a valid approach.&lt;/p&gt;

&lt;p&gt;But over time, the decorators will grow as requirements are added. They’ll collect more and more methods, get more responsibilities and slowly the decorators grow fat. Bugs will soon creep out from under the big pile of methods.&lt;/p&gt;

&lt;p&gt;Stuffing everything inside a single decorator isn’t really a big step up from using Rails’ view helpers. If you want to get the most out of decorators, it’s important to apply the principles of object oriented programming to them as well.&lt;/p&gt;

&lt;p&gt;Here are a couple of code smells I commonly find in decorators.&lt;/p&gt;

&lt;h2 id=&quot;divergent-change&quot;&gt;Divergent Change&lt;/h2&gt;
&lt;p&gt;Large decorators often span multiple pieces of functionality. As requirements change, one decorator finds itself changed multiple times for different requirements. This smell is called Divergent Change.&lt;/p&gt;

&lt;p&gt;It’s an indicator that the Single Responsibility Principle is being violated. And no, “taking care of presentation logic” doesn’t count as a single responsibility here ;-) Groups of closely related methods responsible for a single part of functionality should probably be moved out into their own classes.&lt;/p&gt;

&lt;h2 id=&quot;feature-envy&quot;&gt;Feature Envy&lt;/h2&gt;
&lt;p&gt;When moving unnecessary logic out of a view, it’s often placed into the nearest possible decorator. When doing this, a decorator will start to reach deep into other objects and eventually will be more concerned with other objects rather than itself.&lt;/p&gt;

&lt;p&gt;This this introduces a lot of coupling between objects and makes it hard to refactor. This kind of functionality needs to be moved to a more appropriate decorator.&lt;/p&gt;

&lt;h2 id=&quot;a-smelly-decorator&quot;&gt;A smelly decorator&lt;/h2&gt;
&lt;p&gt;Here’s a decorator to handle the presentation logic of a Git commit. I’ve omitted quite some parts for brevity of the example. I’m using the Draper gem, though you could go with any other solution, or even your own.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class CommitDecorator &amp;lt; Draper::Decorator
  delegate_all

  def author_link
    h.link_to(author.name, h.profile_path(author.username))
  end

  def parent_link
    h.link_to(parent.truncated_sha, h.project_commit_path(project, parent.sha))
  end

  def diff_stats
    h.t('commits.show.diff_stats_html',
        changed: diffs.count,
        additions: diffs.sum(&amp;amp;:additions),
        deletions: diffs.sum(&amp;amp;:deletions))
  end

  def file_changes
    diffs.map do |diff|
      DiffLine.new(
        status_class_for(diff), diff.path, diff.additions, diff.deletions)
    end
  end

  private

  DiffLine = Struct.new(:status_class, :path, :additions, :deletions)

  def status_class_for(diff)
    if diff.deleted?
      'deletion'
    elsif diff.added?
      'addition'
    else
      'change'
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A commits controller may look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class CommitsController &amp;lt; ApplicationController
  decorates_assigned :commits, :commit

  def index
    @commits = find_project.commits
  end

  def show
    @commit = find_project.find_commit_by_sha(params[:sha])
  end

  private

  def find_project
    Project.find(params[:project_id])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are two scenarios here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A list of commits in the project is displayed&lt;/li&gt;
  &lt;li&gt;One commit is displayed along with its changed files&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;problems&quot;&gt;Problems&lt;/h2&gt;
&lt;p&gt;The decorator incorporates both of the smells described above.&lt;/p&gt;

&lt;p&gt;It seems awkward to have a decorator with all these functionalities if all you want to do is to display a summarized commit with only a bit of information.&lt;/p&gt;

&lt;p&gt;It’s reaching into the tiny little details of the other objects quite a lot. It’s very coupled to the internals of diffs especially.&lt;/p&gt;

&lt;h2 id=&quot;making-it-less-envy&quot;&gt;Making it less envy&lt;/h2&gt;
&lt;p&gt;The most alarming issue is the reaching into diffs to gather the file changes. Let’s quickly refactor that into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DiffDecorator&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class DiffDecorator &amp;lt; Draper::Decorator
  delegate_all

  def status_class
    if deleted?
      'deletion'
    elsif added?
      'addition'
    else
      'change'
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note how much that already cleans up the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommitDecorator&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file_changes&lt;/code&gt; is now synonymous to the decorated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diffs&lt;/code&gt;. I’ve added an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alias_method&lt;/code&gt; to keep the same interface, though this is not strictly necessary.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class CommitDecorator &amp;lt; Draper::Decorator
  delegate_all
  decorates_association :diffs

  alias_method :file_changes, :diffs

  def author_link
    h.link_to(author.name, h.profile_path(author.username))
  end

  def parent_link
    h.link_to(parent.truncated_sha, h.project_commit_path(project, parent.sha))
  end

  def diff_stats
    h.t('commits.show.diff_stats_html',
        changed: diffs.count,
        additions: diffs.sum(&amp;amp;:additions),
        deletions: diffs.sum(&amp;amp;:deletions))
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The links to the author and parent commit are better off in their own decorator too. Since parent is also a commit object itself, this implies adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link&lt;/code&gt; method to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommitDecorator&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class AuthorDecorator &amp;lt; Draper::Decorator
  delegate_all

  def link
    h.link_to(name, h.profile_path(username))
  end
end

class CommitDecorator &amp;lt; Draper::Decorator
  delegate_all
  decorates_association :diffs
  decorates_association :author
  decorates_association :parent

  alias_method :file_changes, :diffs

  delegate :link, to: :author, prefix: true
  delegate :link, to: :parent, prefix: true

  def link
    h.link_to(truncated_sha, h.project_commit_path(project, sha))
  end

  def diff_stats
    h.t('commits.show.diff_stats_html',
        changed: diffs.count,
        additions: diffs.sum(&amp;amp;:additions),
        deletions: diffs.sum(&amp;amp;:deletions))
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommitDecorator&lt;/code&gt; only has some delegations for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;author_link&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parent_link&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;dealing-with-divergent-change&quot;&gt;Dealing with Divergent Change&lt;/h2&gt;
&lt;p&gt;I always like to have some kind of default or base decorator for a model which defines the methods commonly used in different contexts. It makes sense for this to be called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommitDecorator&lt;/code&gt;. Whenever &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commit.decorate&lt;/code&gt; is called, it’s automatically decorated with the default decorator.&lt;/p&gt;

&lt;p&gt;Some decorated functionality may only be required in a single context. I prefer to put these into their own decorator classes, so it becomes more obvious where it’s being used, and it’s not hiding in between the common functionality.&lt;/p&gt;

&lt;p&gt;For this example, I’d consider a summarized commit sufficient to be decorated by a default decorator. But the detailed commit definitely needs its own:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Commits
  class DetailedCommitDecorator &amp;lt; Draper::Decorator
    delegate_all

    def initialize(*args)
      super(CommitDecorator.new(*args))
    end

    def diff_stats
      h.t('commits.show.diff_stats_html',
          changed: diffs.count,
          additions: diffs.sum(&amp;amp;:additions),
          deletions: diffs.sum(&amp;amp;:deletions))
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I always namespace these context-specific decorators by the class they’re decorating. When you’ve got many decorators, this allows you to still have an overview.&lt;/p&gt;

&lt;p&gt;I dislike using inheritance with decorators, it feels to be against the nature of a decorator. It’s also confusing when overriding methods from the parent class. Overriding inherited methods may need another approach than overriding methods already defined on the model.&lt;/p&gt;

&lt;p&gt;Therefore, I first wrap the original commit object into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommitDecorator&lt;/code&gt;. This would be equivalent to doing something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Commits::DetailedCommitDecorator.new(CommitDecorator.new(commit))&lt;/code&gt;, but I don’t want to have to think about applying both decorators all the time. Note I’m using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegate_all&lt;/code&gt; in all of my decorators to make sure any method unknown to the decorator is being delegated to the decorated object.&lt;/p&gt;

&lt;p&gt;Extracting the functionality of a detailed commit leaves the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommitDecorator&lt;/code&gt; greatly simplified:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class CommitDecorator &amp;lt; Draper::Decorator
  delegate_all
  decorates_association :diffs
  decorates_association :author
  decorates_association :parent

  alias_method :file_changes, :diffs

  delegate :link, to: :author, prefix: true
  delegate :link, to: :parent, prefix: true

  def link
    h.link_to(truncated_sha, h.project_commit_path(project, sha))
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The last thing to do is to make sure the controller applies the appropriate decorators:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class CommitsController &amp;lt; ApplicationController
  decorates_assigned :commits
  decorates_assigned :commit, with: Commits::DetailedCommitDecorator

  def index
    @commits = find_project.commits
  end

  def show
    @commit = find_project.find_commit_by_sha(params[:sha])
  end

  private

  def find_project
    Project.find(params[:project_id])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Avoid turning your decorators into your view helper surrogates. Avoid creating a tangled mess of methods and responsibilities by appropriately dealing with code smells in your decorators. Don’t be afraid to introduce new decorator classes, but only do so if you can justify their existence.&lt;/p&gt;

&lt;p&gt;What kind of code smells do you frequently encounter in your decorators? Let me know in the comments below!&lt;/p&gt;
</description>
        <pubDate>Wed, 09 Dec 2015 07:20:57 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/12/09/rails-antipattern-fat-decorator.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/12/09/rails-antipattern-fat-decorator.html</guid>
        
        
      </item>
    
      <item>
        <title>Don't index the kitchen sink!</title>
        <description>&lt;p&gt;I was recently cleaning up unused indexes and I found quite a few. These were mostly part of join models from which a reverse association wasn’t required. Consider the following example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class ShoppingCart &amp;lt; ActiveRecord::Base
  has_many :shopping_cart_products
  has_many :products, through: :shopping_cart_products
end

class ShoppingCartProduct &amp;lt; ActiveRecord::Base
  belongs_to :shopping_cart
  belongs_to :product
end

class Product &amp;lt; ActiveRecord::Base
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A very basic design for shopping carts containing products.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ShoppingCartProduct&lt;/code&gt; model has been created using Rails’ model generator, which creates the model class with associations, as well as a migration:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;bin/rails g model CartProduct quantity:integer{1} user:belongs_to product:belongs_to –no-test-framework&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class CreateShoppingCartProducts &amp;lt; ActiveRecord::Migration
  def change
    create_table :shopping_cart_products do |t|
      t.integer :quantity, limit: 1, null: false
      t.belongs_to :shopping_cart, index: true, foreign_key: true
      t.belongs_to :product, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a good practice, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quantity&lt;/code&gt; column has been set to disallow null values. Note the two indexes on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shopping_cart_products&lt;/code&gt; which were created by default.&lt;/p&gt;

&lt;p&gt;It doesn’t actually make a lot of sense to ever display which shopping carts a specific product is in. That means it’s not necessary to be able to query a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ShoppingCartProduct&lt;/code&gt; by its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;product_id&lt;/code&gt;, thus that index is unused. Since Rails generated the model and migration for us, it snuck in really quietly.&lt;/p&gt;

&lt;p&gt;An unused index is a waste of database resources. It takes up storage space, and it slows down &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UPDATE&lt;/code&gt;s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT&lt;/code&gt;s, in this case on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shopping_cart_products&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;Getting rid of this unused index is easy:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class RemoveIndexShoppingCartProductsOnProductId &amp;lt; ActiveRecord::Migration
  def up
    remove_index(:shopping_cart_products, :product_id)
  end

  def down
    add_index(:shopping_cart_products, :product_id)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Always be conscious about adding database indexes. Only add one if you’re really sure you need it.&lt;/p&gt;

&lt;p&gt;As application requirements may change over time, so may the need for indexes. Use database tools to regularly monitor for potentially unused indexes. Be sure to monitor it on the production environment to get the best results.&lt;/p&gt;
</description>
        <pubDate>Thu, 09 Jul 2015 13:13:00 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/07/09/dont-index-the-kitchen-sink.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/07/09/dont-index-the-kitchen-sink.html</guid>
        
        
      </item>
    
      <item>
        <title>Using Enumerable as testing abstraction</title>
        <description>&lt;p&gt;Let’s say you want to import all Belgian beers from a beer export CSV and then save them to your database. After some quick hacking, something like this emerges:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImport
  def initialize(io)
    @io = io
  end

  def import!
    CSV.parse(io.read, headers: true) do |row|
      next unless row[:country] == 'Belgium'

      Beer.create_from_import!(name: row[:name],
                               brewery_name: row[:brewery],
                               country_name: row[:country])
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s even a test for this. Note how it’s cleverly using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringIO&lt;/code&gt; here to get the data in there without using a file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImportTest &amp;lt; ActiveSupport::TestCase
  def test_import_belgian_beers_from_csv
    io = StringIO.new(
      &quot;name,brewery,country\n&quot; \
      &quot;Grimbergen Blonde,Brouwerij Alken-Maes,Belgium\n&quot; \
      &quot;Oatmeal Stout,Left Hand Brewing Company,United States\n&quot; \
      &quot;Grolsch Premium Weizen,Grolsche Bierbrouwerij,Netherlands\n&quot; \
      &quot;Straffe Hendrik Brugse,De Halve Maan,Belgium&quot;
    )

    assert_difference('Beer.count', +2) do
      BelgianBeerImport.new(io).import!
    end

    # Or however something as complicated as this is tested...
    beer1, beer2 = Beer.last(2)

    assert_equal('Grimbergen Blonde', beer1.name)
    assert_equal('Brouwerij Alken-Maes', beer1.brewery_name)

    assert_equal('Straffe Hendrik Brugse', beer2.name)
    assert_equal('De Halve Maan', beer2.brewery_name)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This looks overly complicated though. The test is not only testing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BelgianBeerImport&lt;/code&gt; class, but also the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSV&lt;/code&gt; class and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActiveRecord&lt;/code&gt; itself. In fact, the tests are even hitting the database to verify that the system under test works.&lt;/p&gt;

&lt;p&gt;The class is also restricted to importing CSV data. In fact, the test is supplying CSV data, adding another layer of complexity, since you need to provide &lt;em&gt;valid&lt;/em&gt; CSV. One typo could ruin the beerfest, making this test rather brittle.&lt;/p&gt;

&lt;h2 id=&quot;enumerable-the-coolest-ruby-module&quot;&gt;Enumerable, the coolest Ruby module&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; is awesome! I can go on about it for hours, but many others have already done it before me, so I’ll skip on its basics.&lt;/p&gt;

&lt;p&gt;The important part is that almost every Ruby developer knows its interface. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hash&lt;/code&gt; are enumerable. So are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringIO&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt; (IO is its parent), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dir&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSV&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Struct&lt;/code&gt; and even more.&lt;/p&gt;

&lt;p&gt;On each of these classes you can use the greatness that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; provides:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Find all elements matching /apple/
%w(apple pear banana pineapple).grep(/apple/)

# List all file names in the current folder
Dir.new('.').to_a

# Get the longest line in a file, not counting surrounding whitespaces
File.new('Gemfile').map(&amp;amp;:strip).max_by(&amp;amp;:length)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great, so how does this help here?&lt;/p&gt;

&lt;p&gt;Well, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSV&lt;/code&gt; is enumerable too. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BelgianBeerImport&lt;/code&gt; should be refactored to take advantage of this fact. If we can abstract away from using CSV, it opens up interesting opportunities for our test and codebase.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImport
  def initialize(io)
    @csv = CSV.new(io, headers: true)
  end

  def import!
    @csv.each do |row|
      next unless row[:country] == 'Belgium'

      Beer.create_from_import!(name: row[:name],
                               brewery_name: row[:brewery],
                               country_name: row[:country])
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we’re creating an instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSV&lt;/code&gt; and using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each&lt;/code&gt; to enumerate through the CSV row objects. The tests still pass so all is good!&lt;/p&gt;

&lt;p&gt;This can be taken a lot further though. This test is still testing CSV and ActiveRecord. Let’s inject them as dependencies:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImport
  def initialize(csv, repository = Beer)
    @csv, @repository = csv, repository
  end

  def import!
    @csv.each do |row|
      next unless row[:country] == 'Belgium'

      @repository.create_from_import!(name: row[:name],
                                      brewery_name: row[:brewery],
                                      country_name: row[:country])
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The test has to be adjusted accordingly to pass in the CSV object:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImportTest &amp;lt; ActiveSupport::TestCase
  def test_import_belgian_beers_from_csv
    io = StringIO.new(
      &quot;name,brewery,country\n&quot; \
      &quot;Grimbergen Blonde,Brouwerij Alken-Maes,Belgium\n&quot; \
      &quot;Oatmeal Stout,Left Hand Brewing Company,United States\n&quot; \
      &quot;Grolsch Premium Weizen,Grolsche Bierbrouwerij,Netherlands\n&quot; \
      &quot;Straffe Hendrik Brugse,De Halve Maan,Belgium&quot;
    )

    assert_difference('Beer.count', +2) do
      BelgianBeerImport.new(CSV.new(io, headers: true)).import!
    end

    # Or however something as complicated as this is tested...
    beer1, beer2 = Beer.last(2)

    assert_equal('Grimbergen Blonde', beer1.name)
    assert_equal('Brouwerij Alken-Maes', beer1.brewery_name)

    assert_equal('Straffe Hendrik Brugse', beer2.name)
    assert_equal('De Halve Maan', beer2.brewery_name)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s time to have a good look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BelgianBeerImport&lt;/code&gt; class and squeeze your eyes. If you stop thinking about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@csv&lt;/code&gt; to be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSV&lt;/code&gt; object and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;row&lt;/code&gt; to be a CSV row and think about it as an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt;, it suddenly looks an awful lot like an array containing hashes!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImport
  def initialize(beers, repository = Beer)
    @beers, @repository = beers, repository
  end

  def import!
    @beers.each do |beer|
      next unless beer[:country] == 'Belgium'

      @repository.create_from_import!(name: beer[:name],
                                      brewery_name: beer[:brewery],
                                      country_name: beer[:country])
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s simply renaming a few variables, but the new names make it a lot easier to see everything in a more abstract fashion.&lt;/p&gt;

&lt;p&gt;Time to simplify the test, as the whole CSV part is no longer necessary. Instead we can supply a plain array (also enumerable) with hashes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImportTest &amp;lt; ActiveSupport::TestCase
  def test_import_belgian_beers_from_csv
    beers = [
      { name: 'Grimbergen Blonde', brewery: 'Brouwerij Alken-Maes',
        country: 'Belgium' },
      { name: 'Oatmeal Stout', brewery: 'Left Hand Brewing Company',
        country: 'United States' },
      { name: 'Grolsch Premium Weizen', brewery: 'Grolsche Bierbrouwerij',
        country: 'Netherlands' },
      { name: 'Straffe Hendrik Brugse', brewery: 'De Halve Maan',
        country: 'Belgium' }
    ]
    repository = mock

    repository.expects(:create_from_import!).with(name: 'Grimbergen Blonde',
      brewery_name: 'Brouwerij Alken-Maes', country_name: 'Belgium')
    repository.expects(:create_from_import!).with(name: 'Straffe Hendrik Brugse',
      brewery_name: 'De Halve Maan', country_name: 'Belgium')

    BelgianBeerImport.new(beers, repository).import!
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note how the ActiveRecord dependency got replaced with a simple mock and expectations.&lt;/p&gt;

&lt;p&gt;Let’s take a bit more advantage of the enumerable interface and be more explicit that we’re expecting the enumerable to contain hashes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class BelgianBeerImport
  def initialize(beers, repository = Beer)
    @beers, @repository = beers, repository
  end

  def import!
    @beers
      .map(&amp;amp;:to_hash)
      .select { |beer| beer[:country] == 'Belgium' }
      .each { |beer| create_beer(beer) }
  end

  private

  def create_beer(beer)
    @repository.create_from_import!(name: beer[:name],
                                    brewery_name: beer[:brewery],
                                    country_name: beer[:country])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A CSV row object also has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_hash&lt;/code&gt; method, which converts the row to a real hash. Now it’s obvious what type of values we’re working with. It also allows the enumerable to contain objects that aren’t hashes, as long as they define the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_hash&lt;/code&gt; method and return the data in the required format.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BelgianBeerImport&lt;/code&gt; class has become a lot more flexible. It doesn’t depend on CSV data alone anymore. Instead it has been abstracted into accepting any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; whose values define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_hash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The class has been completely decoupled from other dependencies. Mostly thanks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt;! It’s less complex, and therefore a lot easier to test. As a bonus, the test is blazing fast. Be sure not to blink when running tests like this, otherwise you’ll think it hasn’t even run!&lt;/p&gt;

&lt;p&gt;Combined with duck typing, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt; is a very powerful interface. The fact that many Ruby developers are already familiar with its interface make it the ideal candidate to use for collection interfaces.&lt;/p&gt;
</description>
        <pubDate>Tue, 07 Jul 2015 22:14:00 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/07/07/using-enumerable-as-abstraction-when-testing.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/07/07/using-enumerable-as-abstraction-when-testing.html</guid>
        
        
      </item>
    
      <item>
        <title>Delegating to Query Objects through ActiveRecord scopes</title>
        <description>&lt;p&gt;Query objects are a fairly well known concept in Rails these days. They’re useful to extract complex SQL queries into their own classes, which would otherwise clutter ActiveRecord models. What if you turned a complex scope which is already used all over your application into a query object? Do you have to refactor all of these occurences?&lt;/p&gt;

&lt;p&gt;The following ActiveRecord model has a scope returning popular featured videos. Okay, it’s not really that complex, but this way we can keep the focus on the important parts.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Video &amp;lt; ActiveRecord::Base
  scope :featured_and_popular,
        -&amp;gt; { where(featured: true).where('views_count &amp;gt; ?', 100) }
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The scope can be easily extracted into a query object:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Videos
  class FeaturedAndPopularQuery
    def initialize(relation = Video.all)
      @relation = relation
    end

    def featured_and_popular
      @relation.where(featured: true).where('views_count &amp;gt; ?', 100)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Instead of calling a scope on the model, now the query object can be called:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Videos::FeaturedAndPopularQuery.new.featured_and_popular
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While it’s great to have the logic removed from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Video&lt;/code&gt; class, there are dozens of occurrences of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Video.featured_and_popular&lt;/code&gt; calls scattered across the whole application. It would be great if the interface could remain unchanged, while still having the complex logic handled by the query object.&lt;/p&gt;

&lt;p&gt;To find out how this can be done, let’s first take a look at how Rails implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scope&lt;/code&gt; method. Note that this is a bit simplified, I’ve left out the irrelevant parts:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def scope(name, body, &amp;amp;block)
  unless body.respond_to?(:call)
    raise ArgumentError, 'The scope body needs to be callable.'
  end

  # ...

  singleton_class.send(:define_method, name) do |*args|
    scope = all.scoping { body.call(*args) }
    # ...

    scope || all
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A couple of things catch the attention:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The body (usually a proc) of the scope can be any object, as long as it responds to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoping&lt;/code&gt; method is used to scope the result of the body to the current scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoping&lt;/code&gt; method makes sure that the relation being returned by the scope body is scoped to the relation in the current scope. Wait, that sounds confusing. Check out this example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Video.only_cats.scoping do
  Video.featured_and_popular
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This would return cat videos which are featured and popular. So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoping&lt;/code&gt; scopes the relation inside the block to the scope of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Video.only_cats&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can simply call the query object from the scope. Thanks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoping&lt;/code&gt;, we don’t need to pass the current scope into the query object:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Video &amp;lt; ActiveRecord::Base
  scope :featured_and_popular,
        -&amp;gt; { Videos::FeaturedAndPopularQuery.new.featured_and_popular }
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But this looks quite ugly and verbose.&lt;/p&gt;

&lt;p&gt;As we’ve seen in the implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scope&lt;/code&gt;, it expects its body to be an object which responds to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call&lt;/code&gt;. Right now we’re passing a proc, but this can be replaced with the query object, as long as it responds to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call&lt;/code&gt;. So we can just turn the query object into a callable object by renaming a method:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Videos
  class FeaturedAndPopularQuery
    def initialize(relation = Video.all)
      @relation = relation
    end

    def call
      @relation.where(featured: true).where('views_count &amp;gt; ?', 100)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The proc can be removed from the scope declaration, and the query object itself becomes the scope body:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Video &amp;lt; ActiveRecord::Base
  scope :featured_and_popular, Videos::FeaturedAndPopularQuery.new
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We could take this even further. Since classes are also objects in Ruby, it’s possible to have a class method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call&lt;/code&gt;, which delegates the call to a new instance of the query object:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Videos
  class FeaturedAndPopularQuery
    class &amp;lt;&amp;lt; self
      delegate :call, to: :new
    end

    def initialize(relation = Video.all)
      @relation = relation
    end

    def call
      @relation.where(featured: true).where('views_count &amp;gt; ?', 100)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now only the class has to be passed in as the body of the scope. Judging by the camelcased name, it’s very obvious we’re dealing with a class here.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Video &amp;lt; ActiveRecord::Base
  scope :featured_and_popular, Videos::FeaturedAndPopularQuery
end  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The logic of the query has been extracted to a query object, but the scope has been left in place so other parts of the code don’t need to be changed. The ActiveRecord model looks nice and clean, while the scope is essentially a delegation to the query object.&lt;/p&gt;
</description>
        <pubDate>Mon, 29 Jun 2015 21:10:57 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/06/29/query-objects-through-scopes.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/06/29/query-objects-through-scopes.html</guid>
        
        
      </item>
    
      <item>
        <title>Say no to chained scopes!</title>
        <description>&lt;p&gt;In a Ruby on Rails application, it’s not uncommon to encounter code which reaches deep into the internals and database schema of a model.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Person &amp;lt; ActiveRecord::Base
  enum gender: { male: 1, female: 2 }
end

class PeopleController &amp;lt; ApplicationController
  def index
    @people = Person.where(gender: Person.genders[:male])
                    .where('age &amp;gt;= 18')
                    .where(right_handed: false)

    respond_to(:html)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code has a few problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The controller has way too much knowledge of the database structure of the model. Having these details bleeding into higher layers resists change to the underlying structure.&lt;/li&gt;
  &lt;li&gt;The chain of method calls make it incredibly hard to test if you’re using mocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are implementation details which must be encapsulated within the model. ActiveRecord scopes to the rescue!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Person &amp;lt; ActiveRecord::Base
  enum gender: { male: 1, female: 2 }

  scope :male,        -&amp;gt; { where(gender: 1) }
  scope :adult,       -&amp;gt; { where('age &amp;gt;= 18') }
  scope :left_handed, -&amp;gt; { where(right_handed: false) }
end

class PeopleController &amp;lt; ApplicationController
  def index
    @people = Person.male.adult.left_handed

    respond_to(:html)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The raw SQL and knowledge of model attributes has been encapsulated inside the model. Problem solved … right?&lt;/p&gt;

&lt;p&gt;The testability has been slightly improved, but there’s still a long chain of method calls to combine the different scopes. We still have to summon an army of mocks to test our controller:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class PeopleControllerTest &amp;lt; ActionController::TestCase
  def test_people_index
    adult_finder        = mock
    left_handed_finder  = mock

    Person.expects(:male).returns(adult_finder)
    adult_finder.expects(:adult).returns(left_handed_finder)
    left_handed_finder.expects(:left_handed)

    get :index
    assert_response :success
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Besides expectation ridden, the test is also quite brittle. If the order of scopes changes at some point, the test fails, even though the code being tested still works.&lt;/p&gt;

&lt;p&gt;Another problem may arise with more complex scopes. Scopes can be combined freely, but not all combinations might lead to valid SQL. Testing all combinations is very cumbersome too.&lt;/p&gt;

&lt;p&gt;I prefer to combine the scopes into a single scope or class method inside the model, rather than chaining scopes outside the model. This keeps as much internal as possible, and allows for easier database query optimizations and other changes.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Person &amp;lt; ActiveRecord::Base
  enum gender: { male: 1, female: 2 }

  scope :male,        -&amp;gt; { where(gender: 1) }
  scope :adult,       -&amp;gt; { where('age &amp;gt;= 18') }
  scope :left_handed, -&amp;gt; { where(right_handed: false) }

  class &amp;lt;&amp;lt; self
    def left_handed_male_adults
      left_handed.male.adult
    end
  end
end

class PeopleController &amp;lt; ApplicationController
  def index
    @people = Person.left_handed_male_adults

    respond_to(:html)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The scope chain has been wrapped inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person.left_handed_male_adults&lt;/code&gt; class method. Note that the class method could also have been defined as a scope if you wanted to. The primary difference between the two is that a scope is guaranteed to return an ActiveRecord relation.&lt;/p&gt;

&lt;p&gt;The combined scope leads to a much simpler and more robust test:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class PeopleControllerTest &amp;lt; ActionController::TestCase
  def test_people_index
    Person.expects(:left_handed_male_adults)

    get :index
    assert_response :success
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By avoiding the scope chains outside of the relevant models, the codebase becomes less coupled and therefore easier to maintain and refactor.&lt;/p&gt;

&lt;p&gt;Of course it’s still possible and very to chain the scopes since all scopes are public. Resist the urge of chaining them outside of their model to keep things simple!&lt;/p&gt;
</description>
        <pubDate>Wed, 24 Jun 2015 22:35:57 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/06/24/say-no-to_chained-scopes.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/06/24/say-no-to_chained-scopes.html</guid>
        
        
      </item>
    
      <item>
        <title>A cookie based approach to handling guest users</title>
        <description>&lt;p&gt;Nithin Bekal &lt;a href=&quot;https://nithinbekal.com/posts/gradual-engagement-rails/&quot;&gt;wrote an excellent post&lt;/a&gt; on how to use gradual engagement in Ruby on Rails for guest users by allowing them to publish posts to a site without actually registering.&lt;/p&gt;

&lt;p&gt;This post presents a database-less approach to handling guest users in Rails. It’s not necessarily better than Nithin’s approach, but the general idea is not to bother our database with guest users’ data which eventually has to be cleaned up manually. There also should not be a special treatment for the guest users by the controllers, views and other models.&lt;/p&gt;

&lt;p&gt;This leads to a cookie or session based approach to store a guest users’ data. A cookie based approach means they cannot access the data from different devices. This leaves an incentive for them to actually register, while it’s possible to try out the personalized functionality of the website. It’s also a good option to have an expiration date on the cookie, so guests have to come back in order to keep their data.&lt;/p&gt;

&lt;h2 id=&quot;basic-application-structure&quot;&gt;Basic Application Structure&lt;/h2&gt;

&lt;p&gt;The application is quite vanilla. Registered users can upload videos, and add videos to a watchlist to watch them at a later time. Watchlisted videos are represented by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SavedVideo&lt;/code&gt; model. Devise is used for registration and authentication.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/models/user.rb
class User &amp;lt; ActiveRecord::Base
  has_many :saved_videos

  devise :database_authenticatable, :registerable
end

# app/models/saved_video.rb
class SavedVideo &amp;lt; ActiveRecord::Base
  belongs_to :video
  belongs_to :user

  scope :for_video, -&amp;gt;(video) { where(video: video) }
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Registered users can also view their watchlist. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SavedVideosController&lt;/code&gt; takes care of this and adding videos on the watchlist:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/controllers/saved_videos_controller.rb
class SavedVideosController &amp;lt; ApplicationController
  before_action :authenticate_user!

  def index
    @saved_videos = current_user.saved_videos

    respond_to(:html)
  end

  def create
    video = Video.find(params[:video_id])

    current_user.saved_videos.create!(video: video)
    flash.notice = 'Video saved for later.'

    respond_to do |format|
      format.html { redirect_to(videos_path) }
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The watchlist page looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/views/saved_videos/index.html.slim
.row
  .cols-xs-12
    h1 Saved Videos

    table.table.table-striped
      = render(@saved_videos) || 'No videos saved for later yet'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The saved video partial simply renders the video with an additional surrounding tag for styling purposes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/views/saved_videos/_saved_video.html.slim
.saved-video
  = render(saved_video.video)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The video partial also has a link to add a video to the watchlist, or shows a label if a video is already saved for later:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/views/videos/_video.html.slim
.video
  h2 = video.name
  - if current_user.saved_videos.for_video(video).exists?
    span.label.label-primary On Watchlist
  - else
    a href=video_saved_video_path(video) data-method=&quot;post&quot; Watch later
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The page of all available videos looks like this when adding a video to the watchlist:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/guests/1.jpg&quot; alt=&quot;List of videos and adding a video to the watchlist&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;refactoring-user&quot;&gt;Refactoring User&lt;/h2&gt;

&lt;p&gt;Before moving on to the implementation of the guest user, the interface of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt; model has to be simplified. Right now it looks rather complicated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;current_user.saved_videos.for_video(video).exists?

current_user.saved_videos.create!(video: video)

current_user.saved_videos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first two are using the ActiveRecord API. The guest user won’t be having a database backend, so the ActiveRecord specific calls should be considered an implementation detail, and need to be encapsulated.&lt;/p&gt;

&lt;p&gt;This leads to the following structure for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class User &amp;lt; ActiveRecord::Base
  has_many :saved_videos

  devise :database_authenticatable, :registerable

  def saved_for_later?(video)
    saved_videos.for_video(video).exists?
  end

  def save_for_later(video)
    saved_videos.create!(video: video)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Communication with the user now happens through a few simple calls:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;current_user.saved_for_later?(video)

current_user.save_for_later(video)

current_user.saved_videos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Time to apply these changes to the controller:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class SavedVideosController &amp;lt; ApplicationController
  before_action :authenticate_user!

  # ...

  def create
    video = Video.find(params[:video_id])

    current_user.save_for_later(video)
    flash.notice = 'Video saved for later.'

    respond_to do |format|
      format.html { redirect_to(videos_path) }
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the video partial:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.video
  h2 = video.name
  - if current_user.saved_for_later?(video)
    span.label.label-primary On Watchlist
  - else
    a href=video_saved_video_path(video) data-method=&quot;post&quot; Watch later
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To make sure guest users can actually access the saved video controller, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_action&lt;/code&gt; call should be removed, otherwise they’ll end up on the sign in page.&lt;/p&gt;

&lt;h2 id=&quot;adding-the-guest&quot;&gt;Adding the Guest&lt;/h2&gt;

&lt;p&gt;Preparations have been made for the introduction of the guest user. Let’s log out and see what happens when viewing the video listing:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ActionView::Template::Error (undefined method `saved_for_later?' for nil:NilClass):
    2:   h2
    3:     = video.name
    4:     small&amp;lt;
    5:       - if current_user.saved_for_later?(video)
    6:         span.label.label-primary On Watchlist
    7:       - else
    8:         a href=video_saved_video_path(video) data-method=&quot;post&quot; Watch later
  app/views/videos/_video.html.slim:5:in `_app_views_videos__video_html_slim__3946905160582581419_70363594171520'
  app/views/videos/index.html.slim:5:in `_app_views_videos_index_html_slim___3933902596725860868_70363542529440'
  app/controllers/videos_controller.rb:7:in `index'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Devise exposes the logged in user in a controller method called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_user&lt;/code&gt;. If the user is not authenticated, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_user&lt;/code&gt; simply returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;, leading to the error. So instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;, it should return the guest user object.&lt;/p&gt;

&lt;p&gt;Let’s initially implement it as a Null Object. It won’t do anything yet, but this is a useful way to see if we haven’t missed anything else.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Guest
  def saved_for_later?(video)
    false
  end

  def save_for_later(video)
  end

  def saved_videos
    []
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Override the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_user&lt;/code&gt; method in the controller to return the guest user when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt; is returned:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class ApplicationController &amp;lt; ActionController::Base
  def current_user
    super || guest_user
  end

  private

  def guest_user
    @guest ||= Guest.new
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s check out the application again. Viewing and adding saved videos should work again. Note that when saving a video, it displays the flash message, but it doesn’t actually add it to the watchlist yet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/guests/2.jpg&quot; alt=&quot;Testing with the null object&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There’s something else odd going on too. It displays the option to log out, but we’re a guest user!&lt;/p&gt;

&lt;p&gt;The default way in Devise to check if a user is signed in is with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_signed_in?&lt;/code&gt; method. It simply checks the presence of a current user, so even the guest object would make it return true. The easiest fix is to override the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_signed_in?&lt;/code&gt; method, like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class User &amp;lt; ActiveRecord::Base
  # ...

  def registered?
    true
  end
end

class Guest
  # ...

  def registered?
    false
  end
end

class ApplicationController &amp;lt; ActionController::Base
  # ...

  def user_signed_in?
    current_user.registered?
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that out of the way, it’s time to store a guests’ saved videos in a cookie!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Guest
  def initialize(store)
    @store = store
  end

  def registered?
    false
  end

  def saved_for_later?(video)
    saved_video_ids.include?(video.id)
  end

  def save_for_later(video)
    @store[:saved_for_later] = JSON.generate((saved_video_ids &amp;lt;&amp;lt; video.id))
  end

  def saved_videos
    []
  end

  private

  def saved_video_ids
    return [] unless @store[:saved_for_later]

    JSON.parse(@store[:saved_for_later])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The cookie store is being passed into the initializer, and the ID’s of saved videos are stored inside it in the JSON format. Since the cookie store is a very Hash-like object, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guest&lt;/code&gt; actually doesn’t really have to care that it’s a cookie store, it just pretends it’s a hash! This is useful when testing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guest&lt;/code&gt;, an actual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hash&lt;/code&gt; can be used:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class GuestTest &amp;lt; MiniTest::Test
  def test_save_video_for_later
    store = {}
    video = mock
    guest = Guest.new(store)

    video.expects(:id).returns(23)
    guest.save_for_later(video)

    assert_equal(store, { saved_for_later: '[23]' })
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ApplicationController&lt;/code&gt;, a guest should now be initialized with a cookie store:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class ApplicationController &amp;lt; ActionController::Base
  def user_signed_in?
    current_user.registered?
  end

  def current_user
    super || guest_user
  end

  private

  def guest_user
    @guest ||= Guest.new(cookies.signed)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s check out the changes made to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SavedVideosController&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class SavedVideosController &amp;lt; ApplicationController
  # ...

  def create
    video = Video.find(params[:video_id])

    current_user.save_for_later(video)
    flash.notice = 'Video saved for later.'

    respond_to do |format|
      format.html { redirect_to(videos_path) }
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s right, nothing changed! This is polymorphism at its best! The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create&lt;/code&gt; action doesn’t waste its time caring whether the user is a guest or not. The lack of conditionals greatly boosts the clarity of the controller action!&lt;/p&gt;

&lt;p&gt;The only thing remaining is to display the videos on the watchlist. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;saved_videos&lt;/code&gt; method of a user is expected to return an array-like structure with objects responding to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;video&lt;/code&gt; methods. This is handled by returning a struct:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Guest
  # ...

  def saved_videos
    saved_video = Struct.new(:user, :video) do
      def to_partial_path
        SavedVideo.new.to_partial_path
      end
    end

    Video.where(id: saved_video_ids).map do |video|
      saved_video.new(self, video)
    end
  end

  private

  def saved_video_ids
    return [] unless @store[:saved_for_later]

    JSON.parse(@store[:saved_for_later])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the struct also responds to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_partial_path&lt;/code&gt;, so that Rails knows which partial to render for the object. Let’s see how it works:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/guests/3.jpg&quot; alt=&quot;Guest user browsing the watchlist&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Way cool! A guest user save videos the exact same way registered users can. This is nice to quickly try it out, without having to create an account first. After they register, everything still works the same, familiar way.&lt;/p&gt;

&lt;h2 id=&quot;refactoring-the-guest&quot;&gt;Refactoring the Guest&lt;/h2&gt;

&lt;p&gt;Looking at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guest&lt;/code&gt; class, all it really does is managing the saved videos:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Guest
  def initialize(store)
    @store = store
  end

  def registered?
    false
  end

  def saved_for_later?(video)
    saved_video_ids.include?(video.id)
  end

  def save_for_later(video)
    @store[:saved_for_later] = JSON.generate((saved_video_ids &amp;lt;&amp;lt; video.id))
  end

  def saved_videos
    saved_video = Struct.new(:user, :video) do
      def to_partial_path
        SavedVideo.new.to_partial_path
      end
    end

    Video.where(id: saved_video_ids).map do |video|
      saved_video.new(self, video)
    end
  end

  private

  def saved_video_ids
    return [] unless @store[:saved_for_later]

    JSON.parse(@store[:saved_for_later])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the guest were to do anything in addition, the class becomes bloated really quickly. Let’s fast-forward a couple of refactorings to see a better structure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/models/guest.rb
class Guest
  attr_reader :saved_videos

  def initialize(store)
    @saved_videos = Guests::SavedVideos.new(store)
  end

  def registered?
    false
  end

  def saved_for_later?(video)
    saved_videos.include?(video)
  end

  def save_for_later(video)
    return if saved_for_later?(video)

    saved_videos &amp;lt;&amp;lt; video
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SavedVideos&lt;/code&gt; just got its own, dedicated class. Note that it’s located inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guests&lt;/code&gt; module. Here’s the code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/models/guests/saved_videos.rb
module Guests
  class SavedVideos
    include Enumerable

    delegate :each, to: :to_ary

    def initialize(store)
      @store = store
    end

    def include?(video)
      ids.include?(video.id)
    end

    def &amp;lt;&amp;lt;(video)
      @store[:saved_for_later] = JSON.generate(ids &amp;lt;&amp;lt; video.id)
    end

    # Is called by ActionView when rendering a collection
    def to_ary
      Video.where(id: ids).map do |video|
        Guests::SavedVideo.new(self, video)
      end
    end

    private

    def ids
      return [] unless @store[:saved_for_later]

      JSON.parse(@store[:saved_for_later])
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The low level code of storing data inside the cookie store is in here. Take note of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_ary&lt;/code&gt; method. The struct has been replaced with an actual class. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_ary&lt;/code&gt; is also called by ActionView when passing a collection to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;render&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guest&lt;/code&gt; can treat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guests::SavedVideos&lt;/code&gt; as an array like object, not having to worry about all the implementation details. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guests::SavedVideos&lt;/code&gt; is also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable&lt;/code&gt;, so it actually has a lot of methods arrays do too! This makes it easy to add a little count of saved videos on the website, simply by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_user.saved_videos.count&lt;/code&gt;!&lt;/p&gt;

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

&lt;p&gt;You might want to add restrictions to the guest user, such as a maximum amount of saved videos. And when they exceed the maximum, present them with a register screen to continue saving more videos. I’ll probably cover this in a future post.&lt;/p&gt;

&lt;p&gt;When a guest decides to actually register, it makes sense to import their already saved data into the account as a courtesy.&lt;/p&gt;

&lt;p&gt;Since cookies are transfered with every request to the web server, you might decide to store the data inside the session store. This can be accomplished by one simple change in the controller:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class ApplicationController &amp;lt; ActionController::Base
  def current_user
    super || guest_user
  end

  private

  def guest_user
    @guest ||= Guest.new(session)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s where Rails shines, the session store has the same hash-like interface as a cookie store, making this change extremely simple!&lt;/p&gt;

&lt;p&gt;You might also enable users to erase their data. On the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt;, it’s easy enough to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destroy&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt;. It’s not too hard to implement this for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guest&lt;/code&gt; too:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Guest
  # ...

  def destroy
    saved_videos.destroy
  end

  alias_method :delete, :destroy
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guests::SavedVideos&lt;/code&gt; is then concerned with cleaning up only its own data:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Guests
  class SavedVideos
    # ...

    def destroy
      @store[:saved_for_later] = nil
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It doesn’t fully remove the cookie, but it does clear the data. For whatever reason, you cannot call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt; on a chained cookie…&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This approach works nicely when no guest user data has to be stored inside the database (and even if it does, this can work with a few adjustments!), and you’re not storing a lot of data inside the cookie.&lt;/p&gt;

&lt;p&gt;The greatest benefit in my opinion is that the application remains pretty much unchanged and the implementation details are nicely encapsulated by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guest&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/fivedigit/cookie-based-guests&quot;&gt;full source code on Github&lt;/a&gt;!&lt;/p&gt;
</description>
        <pubDate>Sat, 20 Jun 2015 18:55:57 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/06/20/cookie-based-approach-to-guest-users.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/06/20/cookie-based-approach-to-guest-users.html</guid>
        
        
      </item>
    
      <item>
        <title>Resourceful custom user profile theme</title>
        <description>&lt;p&gt;Imagine we’ve got a Rails application where users can view each other’s profiles. We’d like to enable them to make their profile personal and unique by customizing the background and text colors used to display their profile. In nearby the future, there will likely be many more adjustments users can make to their profile theme. So what would be a good approach for this problem that conforms to the Rails way?&lt;/p&gt;

&lt;p&gt;We’ve already got our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Profile&lt;/code&gt; functionality in place, where a user can have a single profile:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/models/user.rb
class User
  has_one :profile
end

# app/models/profile.rb
class Profile
  belongs_to :user
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the controller to view other user’s public profiles is quite vanilla too:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# app/controllers/profiles_controller.rb
class ProfilesController &amp;lt; ApplicationController
  def show
    @profile = User.find(params[:id]).profile

    respond_to(:html) if stale?(@profile)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there’s of course the profile view:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;!-- app/views/profiles/show.html.erb --&amp;gt;
&amp;lt;div class=&quot;profile&quot;&amp;gt;
  &amp;lt;h1&amp;gt;&amp;lt;%= @profile.name %&amp;gt;&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;Location: &amp;lt;%= @profile.location %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I won’t go into the details of the form to edit the profile settings itself, but we’ll store the color codes in two attributes on profile called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreground_color&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background_color&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are a couple of ways we can implement the profile theming:&lt;/p&gt;

&lt;h2 id=&quot;inline-styles&quot;&gt;Inline styles&lt;/h2&gt;

&lt;p&gt;This is the fastest way to get it done, and also the fastest way to turn your frontend code into a tangled mess. A definite no-go unless you really like digital spaghetti.&lt;/p&gt;

&lt;h2 id=&quot;including-css-in-style-tags&quot;&gt;Including CSS in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tags&lt;/h2&gt;

&lt;p&gt;A little better, but not quite enough separated yet. Everything is still rendered within the same view. I don’t feel like this is the most logical option, especially not in the longer run when the functionality expands.&lt;/p&gt;

&lt;h2 id=&quot;rendering-css-in-a-stylesheet&quot;&gt;Rendering CSS in a stylesheet&lt;/h2&gt;

&lt;p&gt;This option makes the most sense to me. This keeps the data nicely separated from the styles, and doesn’t throw everything on a single pile of code.&lt;/p&gt;

&lt;p&gt;It’s also a very resourceful approach. We’re considering the stylesheet to be the &lt;em&gt;representation of a profile in CSS format&lt;/em&gt;. This fits in nicely with the way Rails works, our controller only needs a minor change:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class ProfilesController &amp;lt; ApplicationController
  def show
    @profile = User.find(params[:id]).profile

    respond_to(:html, :css) if stale?(@profile)
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, the CSS view needs to be implemented:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/* app/views/profiles/show.css.erb */
.profile {
  background-color: &amp;lt;%= @profile.background_color %&amp;gt;
}

.profile p {
  color: &amp;lt;%= @profile.foreground_color %&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Right now there are only two simple attributes, but when profile customization functionality extends, it might be a good idea to start using a decorator at some point.&lt;/p&gt;

&lt;p&gt;So now that we’ve got our  stylesheet done, it needs to be included in the page to see the custom theme. We’ll do this using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;content_for&lt;/code&gt; in the profile HTML view:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;!-- app/views/profiles/show.html.erb --&amp;gt;
&amp;lt;% content_for :stylesheet_includes do %&amp;gt;
  &amp;lt;%= stylesheet_link_tag(profile_path(@user, format: :css)) %&amp;gt;
&amp;lt;% end %&amp;gt;

&amp;lt;div class=&quot;profile&quot;&amp;gt;
  &amp;lt;h1&amp;gt;&amp;lt;%= @profile.name %&amp;gt;&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;Location: &amp;lt;%= @profile.location %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, we’ll render the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stylesheet_includes&lt;/code&gt; content in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of the page by adding a line to the application layout:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;!-- app/views/layouts/application.html.erb --&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;%= yield :stylesheet_includes %&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s it! If the user visits a profile, the stylesheet with the theme for that profile is applied to the page. This is a nice separation of concerns, made super easy by Ruby on Rails.&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Jun 2015 18:10:00 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/06/02/resourceful-custom-user-profile-theme.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/06/02/resourceful-custom-user-profile-theme.html</guid>
        
        
      </item>
    
      <item>
        <title>Don't use before_action to load data</title>
        <description>&lt;p&gt;Controller filters are a common sight in Ruby on Rails controllers. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_filter&lt;/code&gt; specifically can be used to halt the request cycle. This is useful to prevent unauthorized access to controller actions, but it’s also very often used to load database records.&lt;/p&gt;

&lt;p&gt;Take a look at this controller:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class TreesController
  before_action :authenticate_user!
  before_action :find_forest
  before_action :find_trees
  before_action :find_tree, except: [:index, :new, :create]

  def index
  end

  def show
  end

  def edit
  end

  def update
    if @tree.update(tree_params)
      redirect_to(@tree)
    else
      render('edit')
    end
  end

  private

  def find_forest
    @forest = Forest.find(params[:forest_id])
  end

  def find_trees
    @trees = @forest.trees
  end

  def find_tree
    @tree = @trees.find(params[:id])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_action&lt;/code&gt; filters have been used to make the controller DRY. The forest and trees are loaded by the filters and assigned to instance variables.&lt;/p&gt;

&lt;p&gt;The views for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edit&lt;/code&gt; have access to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@tree&lt;/code&gt; instance variable, but this isn’t obvious. You have to look at the controller and connect the dots to figure out which variables are available where.&lt;/p&gt;

&lt;p&gt;Perhaps the controller has become too DRY. The filters are coupled to the controller actions in a very weird way. In fact, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:find_trees&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:find_tree&lt;/code&gt; filters are coupled to &lt;em&gt;each other&lt;/em&gt; as well, because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:find_tree&lt;/code&gt; depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:find_trees&lt;/code&gt;. In terms of the problem domain, it becomes hard to see the forest through the trees (pun intended).&lt;/p&gt;

&lt;p&gt;In other words, clarity has been sacrificed for the sake of DRY-ness. Don’t get me wrong, DRY is a great concept, but not when it turns your Rails controller into a complicated puzzle!&lt;/p&gt;

&lt;p&gt;In my opinion, before filters should only ever be used to do what they do best: halting the request cycle. They should not be used for data loading and preparing state.&lt;/p&gt;

&lt;p&gt;Applying that to our controller would result in something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class TreesController
  before_action :authenticate_user!

  def index
    @trees = find_forest.trees
  end

  def show
    @tree = find_tree
  end

  def edit
    @tree = find_tree
  end

  def update
    @tree = find_tree

    if @tree.update(tree_params)
      redirect_to(@tree)
    else
      render('edit')
    end
  end

  private

  def find_tree
    find_forest.trees.find(params[:id])
  end

  def find_forest
    Forest.find(params[:forest_id])
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The filters which were previously loading data have been replaced with plain method calls from the controller actions. Now it’s immediately obvious which data is loaded where.&lt;/p&gt;
</description>
        <pubDate>Sun, 31 May 2015 10:45:57 +0000</pubDate>
        <link>https://craftingruby.com/posts/2015/05/31/dont-use-before-action-to-load-data.html?utm_source=syndication&amp;utm_medium=rss&amp;utm_campaign=blogpost</link>
        <guid isPermaLink="true">https://craftingruby.com/posts/2015/05/31/dont-use-before-action-to-load-data.html</guid>
        
        
      </item>
    
  </channel>
</rss>
