---
title: "DRYing up Rails Views with View Carriers and Services"
description:
  "Rails views can get complicated with all sorts of business logic. In this
  blog we are going to show how we made Rails views simpler by using Carriers."
canonical_url: "https://www.bigbinary.com/blog/drying-up-rails-views-with-view-carriers-and-services"
markdown_url: "https://www.bigbinary.com/blog/drying-up-rails-views-with-view-carriers-and-services.md"
---

# DRYing up Rails Views with View Carriers and Services

Rails views can get complicated with all sorts of business logic. In this blog
we are going to show how we made Rails views simpler by using Carriers.

- Author: Vipul
- Published: December 2, 2014
- Categories: Rails

Anyone who has done any Rails development knows that views gets complicated very
fast. Lately we've been experimenting with Carriers ( also called view services
) to clean up views.

There are many already solutions already existing to this problem like
[Draper Gem](https://github.com/drapergem/draper) , or Cells from
[Trailblazer architecture](https://github.com/apotonick/trailblazer).

We wanted to start with simplest solution by making use of simple ruby objects
that takes care of business logic away from views.

## A complex view

Consider this user model

```ruby
class User
  def super_admin?
    self.role == 'super_admin'
  end

  def manager?
    self.role == 'manager'
  end
end
```

Here we have a view that displays appropriate profile link and changes css class
based on the role of the user.

```erb

<% if @user.super_admin? %>
  <%= link_to 'All Profiles', profiles_path %>
<% elsif @user.manager? %>
  <%= link_to 'Manager Profile', manager_profile_path %>
<% end %>

<h3 class="<%= if @user.manager?
                  'hidden'
               elsif @user.super_admin?
                  'active'
               end %>">

   Hello, <%= @user.name %>
</h3>
```

## Extracting logic to Rails helper

In the above case we can extract the logic from the view to a helper.

After the extraction the code might look like this

```ruby
# app/helpers/users_helper.rb

module UsersHelper

  def class_for_user user
    if @user.manager?
      'hidden'
    elsif @user.super_admin?
      'active'
    end
  end

end
```

Now the view is much simpler.

```erb
<h3 class="<%= class_for_user(@user) %>">
   Hello, <%= @user.name %>
</h3>
```

## Why not to use Rails helpers?

Above solution worked. However in a large Rails application it will start
creating problems.

`UsersHelper` is a module and it is mixed into `ApplicationHelper`. So if the
Rails project has large number of helpers then all of them are mixed into the
`ApplicationHelper` and sometimes there is a name collision. For example let's
say that there is another helper called `ShowingHelper` and this helper also has
method `class_for_user`. Now `ApplicationHelper` is mixing in both modules
`UsersHelper` and `ShowingHelper`. One of those methods will be overridden and
we would not even know about it.

Another issue is that all the helpers are modules not classes. Because they are
not classes it becomes difficult to refactor helpers later. If a module has 5
methods and if we refactor two of the methods into two separate methods then we
end up with seven methods. Now out of those seven methods in the helper only
five of them should be public and the rest two should be private. However since
all the helpers are modules it is very hard to see which of them are public and
which of them are private.

And lastly writing tests for helpers is possible but testing a module directly
feel weird since most of the time we test a class.

## Carriers

Lets take a look at how we can extract the view logic using carriers.

```ruby
class UserCarrier
  attr_reader :user

  def initialize user
    @user = user
  end

  def user_message_style_class
    if user.manager?
      'hidden'
    elsif user.super_admin?
      'active'
    end
  end
end
```

In our controller

```ruby
  class UserController < ApplicationController
    def show
      @user = User.find(params[:id])
      @user_carrier = UserCarrier.new @user
    end
  end
```

Now the view looks like this

```erb

<% if @user.super_admin? %>
  <%= link_to 'All Profiles', profiles_path %>
<% elsif @user.manager?%>
  <%= link_to 'Manager Profile', manager_profile_path %>
<% end %>

<h3 class="<%= @user_carrier.user_message_style_class %>">
  Hello, <%= @user.name %>
</h3>
```

### No html markup in the carriers

Even though carriers are used for presentation we stay away from having any html
markup in our carriers. That is because once we open the door to having html
markups in our carriers then carriers quickly get complicated and it becomes
harder to test them.

### No link_to in the carriers

Since carriers are plain ruby objects, there is no `link_to` and other helper
methods usually. And we keep carriers that way. We do not do
`include ActionView::Helpers::UrlHelper` because the job of the carrier is to
present the data that can be used in `link_to` and complement the usage of
`link_to`.

We believe that `link_to` belongs to the ERB file. However if we really need to
have an abstraction over it then we can create a regular Rails helper method. We
minimize usage of Rails helper, we do not avoid it altogether.

## Overcoming Double Dots

Many times in our view we end up doing

```erb
  Email Preference for Tuesday: <%= @user.email_preferences.tuesday_preference %>
```

This is a violation of
[Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter) . We call it
"don't use Double Dots". Meaning don't do `@article.publisher.full_name`.

Its just a matter of time before views code looks like this

```erb
  <%= @article.publisher.active.not_overdue.try(:full_name) %>
```

Since carriers encapsulate objects into classes, we can overcome this "double
dots" issue by delegating behavior to appropriate object.

```ruby
class UserCarrier
  attr_reader :user :email_preferences

  delegate :tuesday_preference, to: :email_preferences

  def initialize user
    @user = user
    @email_preferences = user.email_preferences
  end

end
```

After that refactoring we end up with cleaner views like.

```erb
  Email Preference for Tuesday: <%= @user_carrier.tuesday_preference %>
```

Note that "Double dot" is allowed at other parts of the code. We do not allow it
in views.

## Testing

Since the carriers are simple ruby objects it's easy to test them.

```ruby
require 'test_helper'

class UserCarrierTest < ActiveSupport::TestCase
  fixture :users

  def setup
    manager = users(:manager)
    @user_carrier = UserCarrier.new manager
  end

  def test_css_class_returned_for_manager
    assert_equal 'hidden', @user_carrier.user_message_style_class
  end

end
```

## Summary

Carriers allow us to encapsulate complex business logic in simple ruby objects.

This helps us achieve clearer separation of concern, clean up our views and
avoid skewed and complex views. Our views are free of "double dots" and we end
up with simple tests which are easy to maintain.

We decided to call it a "carrier" and not "presenter" because the word
"presenter" is overloaded and has many meanings.

We at BigBinary take a similar approach for extracting code from a fat
controller or a fat model. You can find out more about it
[here](https://www.bigbinary.com/videos/learn-ruby-on-rails/using-services-to-manage-code).

## Links

- [Human page](https://www.bigbinary.com/blog/drying-up-rails-views-with-view-carriers-and-services)
