Hashrocket.com / blog

Large cupcake

LittleDecorator Gem: Rails Model Decoration in 42 Lines

posted on and written by Vic Ramon in

Image 100x100 vic ramon

We usually hand-roll our own decorators here at Hashrocket. After doing this a few times I've found a pattern that I really like, and now I've turned it into a gem called LittleDecorator. This gem delivers on its name: there are only 42 lines of code in lib. This blog post explains how to use it and how it works.

Create a Decorator

First create a decorator that subclasses LittleDecorator:

# app/decorators/post_decorator.rb
class PostDecorator < LittleDecorator
end

You can call model methods directly:

def full_title
  "#{title}: #{subtitle}"
end

You can override model methods, but make sure to prefix calls to the original model with record (or its alias model) to avoid an infinite loop:

def updated_at
  record.updated_at.strftime("%A, %B %e, %Y")
end

Helper methods are available to you:

def price
  number_to_currency price
end

As well as route helpers:

def post_link
  link_to title, record
end

Decorate Models

LittleDecorator gives you a decorate helper method that's available in both controllers and views. Just pass it a model to get the decorated version. Calling decorate on a collection will return an array of decorated objects:

decorated_post = decorate(post)
decorated_posts = decorate(posts)

How It Works

LittleDecorator uses method_missing to send any unimplemented methods to the model. If the method is not found in the model, then it checks to see if the view context of the object responds to the method -- that's how you get free access to view helpers and route helpers. If the method is still not found then you'll get a NoMethodError on the decorator.

The decorate helper method works by looking for a decorator with the same class name as the model but with a suffix of "Decorator":

decorator_class = "#{model.class.name}Decorator".constantize

Extras

Decorated records also behave well when used in a link_to:

<%= link_to decorated_post.title, decorated_post %>

That covers most everything you might want to know about this gem. Maybe it can save you some hassle the next time you need a decorator.

Check it out on GitHub.

Posted in Community