Posts Tagged design patterns

Rails Misapprehensions: Helpers are shit.

Wednesday, October 5th, 2011

When I started using Rails years ago I found helpers extremely cool. I could call a method in a view and it would help me by doing something. The method was simply there, no need to worry about its source and how to access it, just call it.

I got older, wiser, and more opinionated. I still like the concept of helpers – of methods. However, the way helpers are implemented in Rails sucks. Also, having object-disoriented functions in your view brings us back to the years where OOP still had to be invented.

In this post I’d like to discuss why I dislike Rails helpers and how to get out of that misery.

What’s a helper?

In Rails, a helper is a function.

<h2>
  Hello, <%= capitalize @user.name %>
</h2>

Here, the #capitalize method helps me capitalizing the username, which is freaking awesome. As this is pretty simple behaviour, let’s call helpers like this utility methods. They modify the input parameter, compute something or escape strings. Pretty straight-forward.

As a second example, I’d like to show a more complex helper.

<div id="sidebar">
  <%= render_news_for @user %>
</div>

This helper will iterate through news items for a particular user and render markup, maybe using several partials. Since it actively renders templates, let’s call this a view component.

Why are helpers shit?

At first sight, using helpers rocks. Capitalizing a string works like a charm – I simply call a function and it happens.

However, looking at the first helper I can identify several drawbacks.

module StringHelper
  def capitalize(string)
    string.capitalize
  end
  • Helpers in Rails are modules, which do not allow inheritance. If I’d need a foreign method I’d have to include another module into the helper module. Not a big deal.
  • Using the #capitalize methods happens without a receiver. The method is globally available in the view since Rails somehow mixes the helper into the view. So, what happens if I have two #capitalize methods in two different helpers mixed in the same view? I don’t have a clue. Do you?

Before getting to solutions, let me discuss another issue with helpers: Another real problem is the implementation in Rails – how these functions are made available to the view.

Helpers in Rails

Again, I’m not talking about how #form_for or #url_for are written internally, I’m talking about how these methods get into the view.

In Rails 3, all helpers are mixed into the view automatically, you still can insert additional modules using the controller’s helper facilities.

class HomeController < ApplicationController
  helper StringHelper

It’s not that the implementation as-it is bad code or something, it is the idea of magically mixing methods into the view instance to make them globally available. This adds complexity to the Rails core, namely around 280 LOCs. Just to mix some methods into the view.

Helpers are shit.

I desperately tried to demonstrate the major disadvantages of helpers in Rails. To summarize.

  1. I like utility methods. There is nothing wrong with having those little “helpers” in your view. What I don’t like is that they are called without an obvious receiver – they look and feel like functions. This is wrong.
  2. The way Rails mixes helpers into the view is error-prone and sucks. Following a slightly different approach there’s no need for all that complexity.
  3. Complex helpers suck. I do believe in view components and the need for those but they shouldn’t be rendering helper methods.

Moaning is fine, but let’s see how things could be changed.

Solution 1: Push Utility Methods into Decorators.

Luckily, a bunch of people feel uncomfy about the current helper architecture. My friend Steve Klabnik wrote a nice article about Jeff Casimir’s draper gem which introduces the Decorator pattern into Rails’ view layer.

Basically, the draper gem wraps existing model instances and provides utility (“helper”) methods on the decorated instance. Here’s an example.

class ArticleDecorator < ApplicationDecorator
  decorates :article
 
  def published_at
    model.published_at.strftime("%A, %B %e")
  end

Now that we defined the Decorator we can use it to wrap the actual model.

@article = ArticleDecorator.decorate(Article.find(1))

The wrapped model can then be used in the view.

<li>
  <%= @article.published_at %>
</li>

The interesting point is that we call the utility helper on the wrapped model which clearly states a receiver. No need for a homeless, global helper function. This way, we can have cleanly separated, domain-focused helpers for models. Decorators also allow inheritance and all other OOP features, since they are just objects.

Decorators are a solid technique when it comes to – well – decorating models. What can we do if there’s no matching model, for instance, when we need to call #url_for?

Solution 2: Use the Controller Instance as View Context

To learn more about that we should peek at the rendering cycle in Rails. What happens when a controller renders a template?

  1. An ActionView instance is created (this will be the “context”).
  2. The controller manages a magical module that contains all helper methods. This module is now mixed into the ActionView instance to make helpers available. I already discussed the need for hundreds of lines of code in order to achieve this “knowledge transfer” from the controller to the view.
  3. Next, instance variables from the controller are copied to the view instance as well.

These are 3 completely useless steps. Completely. Every template engine, whether it be Rails’ internal or tilt requires a so called view context whenever a template is rendered. Both instance variables and methods (that is, helper calls) used within the template are looked up on this view context instance.

Now, there is absolutely no reason for having a separate ActionView instance as view context! We can simply use the controller instance as context object and everything would work. No need to copy over variables, no need to transfer “helpers” to the view instance.

“Helpers” would be modules mixed into the controller – and that’s it.

class HomeController < ApplicationController
  include UrlMethods
 
  def show
    @link = link_to(home_url)

Notice how we can use the mixed-in “helper” methods in the controller instance – we simply included them.

<a href="<%= home_path %>">

The cool thing is we can also use the utility methods in the view which will be invoked on the controller instance, again. No magic copying, just modules.

The Cells project currently is experimenting with this approach and things work out fine. Will blog.

I can hear people now moan about too many mixed-in methods in their ActionController – and they are right! Again, this is due to Rails’ monolithic view/controller design. If one single controller is responsible for rendering an entire web page, then this controller has a lot of responsibilities – too many. That’s why we should use Cells to split up the view into components, which is discussed next.

Solution 3: Use View Components instead of Complex Helpers.

Helpers that compute data and render partials are scary. Often, there is too much concerns in the little helper.

def render_news_for(user)
  items = user.find_news
  render "shared/news", :items => items
end

Let’s assume the _news partial should be reusable throughout your application, needs some special helper function #sanitize and does caching.

<% cache do
  <%- for item in items %>
    <%= sanitize item.text %>
  <% end %>
<% end %>

Several problems here.

  • Every controller has to take care of requiring the special SanitizerHelper for the partial.
  • Caching happens by using helpers, again, which is no good .

Moving the partial and its behaviour into a cell would cleanly separate concerns. The cell could be used as view context and thus provide utility methods itself.

class NewsCell < Cell::Base
  cache :show
 
  def show(items)
    @items = items
    render
  end
 
  def sanitize(string)
    # ...
  end

This creates a reusable view component with a defined scope. Intentionally, I keep the cells discussion briefly as this would break the mold.

Combining Decorators and Cells

Using draper’s decorators within cells is what I figure a fantastic option. Where the decorator cleanly wraps the model object and provides utility methods for tweaking model data the cell separates the concern into a reusable view component, provides a limited scope and generic helper methods (like #url_for), and even caching!

I really don’t care whether draper, cells, or whatever replaces helpers – all I want is less magic code, more object-orientation and rock-solid software. This was a long post – gimme some feedback in the comments section or tweet me

Rails Misapprehensions: The Dependency Injection Pattern

Monday, August 15th, 2011

Inspired by the Stop hating Java post by my friend Andrzej I started to identify the pros and cons of a pattern called Dependency Injection in the Ruby/Rails world. Before I explain the pattern, let me discuss the problem – a dependency.

What is a Dependency?

Let’s say we’re working in a casual Rails controller instance. Whenever we access an object (or class) instance different to the current controller instance (i.e. self), we’re creating a dependency. Dependency here means the controller needs to know class and method names in another domain. Here are some typical dependencies found in many controller actions.

def show
  @comments = Comment.find(:all)

Here, the action knows both where and how to find the comments. It’s a dependency to the model layer.

def update
  # ...
  logger.notice "Comment #{@text} updated."

In this example, we have a strong dependency to the logger component – looking into the Rails code we can see that the #logger method in turn creates a logger instance, so we have to know about instantiation and usage of the logger.

%h1 Welcome, #{current_user.name}

This partial uses a helper method #current_user, which in turn queries controller and request in order to find the current user instance.

What’s the Problem with Dependencies?

Now, the examples above are code you’re gonna find in almost any Rails application – and there’s nothing wrong with that! However, problems might appear as soon as you want to test components separately.

For instance, what if I’d like to test my logging code within the controller, like asserting that the correct message is logged when something special happens?

it "logs correctly" do
  put :update
  assert_equal "Comment Yo! updated.", 
    @controller.logger.last_notice

I’d have to mock the logger instance to make it “testable”, here, to provide the #last_notice method.

Let’s say the original #logger method looks like this.

  def logger
    @logger ||= Rails::SmokeSignalLogger.new
  end

To mock the logger, people overwrite the respective method in the test case.

ActionController.class_eval do
  def logger
    @logger ||= Test::MockedLogger.new
  end

Code like this changes the logger for the entire test suite and might break other tests. A common solution is to reset the original method after each test. In other words, we change a global property for a local test – and this is wrong.

Another Problem: Configurability

In addition to the testing problems we get with dependencies, what if my colleagues love the way I program and plan to use one of my modules in their software (highly improbable). However, they don’t want the SmokeSignalLogger since they’re not speaking Indian, but they want to use another logging layer JungleDrumsLogger?

As soon as my component is imported in their application they’d probably monkey-patch my code to “configure” it.

NicksControllerMethods.class_eval do
  def logger
    @logger ||= 
      JungleDrumsLogger.new(:flavor => :coconut)
  end

I personally consider monkey-patching a code smell.

What’s a component?

Ok. I showed a couple of examples about dependencies and I used the word component a lot. The reason for this is: The Dependency Injection pattern is only applicable in software systems consisting of separated components. The idea is that outer components inject dependencies into smaller components.

A component as it might be a piece of software like a controller instance, an ActiveRecord row instance or a logger object. I see three attributes to make something a component.

  • First, a component has a limited scope of interest. It’s field of work is bounded to some special duty (logging messages, rendering a comments box, …).
  • Second, a component instance cannot access properties of other components, unless you’re providing a way to do so. For example, the logger may not access variables of the controller and vice-versa.

Dependency Injections in Rails

To get back to our examples, let’s see how we could apply DI to get rid of the logger dependency. Don’t let the controller create it itself, but do that on the outside and pass – “inject” – the object into the controller.

One flavor of DI is called Constructor Injection and would imply we inject the logger in the constructor.

class ActionController < ...
  def initialize(..., logger)
    @logger = logger
  end

Obviously, the outer framework would have to take care of creating and passing the logger.

  logger = BushDrumsLogger.new
  controller = ActionController.new(..., logger)

A second form is called Setter Injection where the controller exposes a writer for the injected attribute.

class ActionController < ...
  attr_writer :logger

Both the using frameworks or the test case can set the logger without overriding any code at all.

  controller.logger = TubeMailLogger.new

Cells and DI

One huge problem I see with Rails and DI is: currently, there are not enough components. We got one monolithic ActionController instance, a couple of row models and a global view instance – that’s it. This doesn’t make Rails a bad thing, or thousands of well-running apps out there!

However, the missing components in Rails make it hard to write reusable software and test these in isolation. That’s why we got the Cells gem – it provides reusable view components for Rails and goes perfectly together with DI.

Say we have a sidebar widget that displays the recent comments from your blog. A cell encapsulates that part of the page, the data aggregation and the rendering (read this post if you need a quick introduction to Cells).

Injecting the logger, ouch!

If we needed a special logging mechanism for the widget we could pass it into the component. I don’t know why a widget displaying comments would need to log, but let’s assume it.

%h1 My great blog
 
#sidebar
  = render_cell(:sidebar, :comments, logger)

The cell could then use the external logger without creating a dependency.

class SidebarCell < Cell::Base
  def comments(logger)
    logger.notice "Displaying comments at #{Time.now}!"
 
    render
  end

The additional arguments from the #render_cell invocation are directly passed as method arguments – this is what we call state-args in Cells.

It’s obvious that another project using that sidebar component could inject a completely different logger instance.

Testing with DI

The limited scope of a cell makes it pretty easy to test. Not only can we test that object-oriented “partial” in complete isolation but also can we pass in a mocked logger easily.

it "should render beautifully" do
  render_cell(:sidebar, :comments, mock_logger).
    should have_selector("ul")
end
 
it "should log correctly" do
  logger = ArrayLogger.new
  render_cell(:sidebar, :comments, logger)
 
  logger.last.should match /Logging/
end

No need to change or reset any global here, just throw-away instances and we’re done!

Conclusion

I can’t think of a cleaner solution for dissolving dependencies like these. The DI pattern makes it easy to keep your components dumb. The problem is that you first have to identify your dependencies, then refactor to components and inject instances from the controller (or wherever else).

Especially in Rails, Cells help to build a real MVC application with a data-aggregating ActionController (I call this FrontController) and fine-grained view components that get additional dependencies from the outside.