Hashrocket.com / blog

Bg default article large

Hashrocket's 12 Gems of Christmas

posted on and written by Johnny Winn in

Image 100x100 johnny winn

The holiday season is upon us and what better way to celebrate than to share some gems.

Inspired by Mike Perham's 12 Gems of Christmas, I thought it would be a great chance to mention some of our gems of choice. These are some of our "go to" gems when solving problems or implementing solutions. Each day until Christmas, I'll add a new gem to this post so be sure to check back!

On the First Day of Christmas - Draper

Every holiday needs some decoration so we will kick off the 12 days of Christmas by looking at Draper. Draper is a gem that applies the decorator pattern to your domain objects in Rails. This allows you to take an object-oriented approach in dealing with helpers and prevents cluttering up your domain objects with presentation logic. Here is a quick example:

class PersonDecorator < Draper::Decorator
  def full_name
    model.first_name + " " + model.last_name
  end
end

In your controller:

class PersonController < ApplicationController
  def show
    @person = PersonDecorator.new(Person.find(params[:id]))
  end
end 

And your view:

<%= @person.full_name %>

On The Second Day of Christmas - Decent Exposure

It's so cold this time of year so be careful how much you expose. Instance variables are meant to be private. Decent Exposure lets you expose methods to your views and preserve encapsulation. Recently this precious gem hit the 2.0 milestone and added an array of new features.

Decent Exposure lets you take this:

class PersonController < ApplicationController
  def new
    @person = Person.new(params[:person])
  end

  def create
    @person = Person.new(params[:person])
    if @person.save
      redirect_to(@person)
    else
      render :new
    end
  end

  def edit
    @person = Person.find(params[:id])
  end

  def update
    @person = Person.find(params[:id])
    if @person.update_attributes(params[:person])
      redirect_to(@person)
    else
      render :edit
    end
  end
end

And transform it into this:

class PersonController < ApplicationController
  expose(:person)

  def create
    if person.save
      redirect_to(person)
    else
      render :new
    end
  end

  def update
    if person.save
      redirect_to(person)
    else
      render :edit
    end
  end
end

On the Third Day of Christmas - Dirty

Is your test list getting longer? Want to find out who's are naughty or nice? Dirty is a gem that runs your updated tests based on their git status. This can be a major time saver as your test suite grows because you can run your implementation's tests without invoking the entire suite. Dirty also allows you to specify an argument to scope which type of test you want to execute.

$ dirty
$ dirty spec
$ dirty feature

On The Fourth Day of Christmas - Hitch

Holiday hacking is better in pairs so make sure everyone gets credit with hitch! Hitch combines the pair into a single author in your commit and creates a unique email address.


Author: Johnny Winn and Travis Anderson
     <dev+nurugger07+syntaxritual@hashrocket.com>

This email address can then be used to create a gravatar. Make sure you get hitched this holiday!

On The Fifth Day of Christmas - Fabrication

The elves are hard at work in the toy factory but you don't have to be. Fabrication lets you quickly generate your objects as needed. Simply define your object schematics and then call them from anywhere in your app or specs. The gem supports most common object types like ActiveRecord, Mongoid Documents, Sequel, and DataMapper but also includes Keymaker Nodes and basic class objects.

The simplest way to fabricate an object it to define a Fabricator and pass the name to Fabricate:


Fabricator(:toy) do
  name "Sphero"
  description "Cool Robot"
end

Fabricate(:toy)

# => <Toy name: "Sphero", description: "Cool Robot">

Attributes can also be overridden at the time of fabrication:


Fabricate(:toy, name: "Parrot Drone")

# => <Toy name: "Parrot Drone", description: "Cool Robot">

Also, the sequence feature works perfectly for generating multiple unique objects:


Fabricator(:toy) do
  name { sequence(:name) { |i| "Sphero version #{i}.0" } }
end

3.times do
  Fabricate(:toy)
end

# => <Toy name: "Sphero version 1.0">
# => <Toy name: "Sphero version 2.0">
# => <Toy name: "Sphero version 3.0">

On The Sixth Day of Christmas - FFaker

Trying to express your excitement for the holidays? So many things to say but finding the right words can be hard. Why not fake it? Or at least use FFaker to fake it for you. FFaker is a faster port of Data::Faker from Perl used to generate fake data. It covers everything from names to phone numbers and even IP addresses. This little gem is the gift that keeps on giving, giving fake data that is.

Need a fake name?


Faker::Name.name

# => "Nathanael Feil II"

What about a title using the latest buzz words?


Faker::Name.title

# => "Cheif Data Director"

Faker can even be paired with Fabrication to help generate unique objects:


Fabricator(:elf) do
  name { Faker::Name.name }
  title { Faker::Name.title }
end

3.times do
  Fabricate(:elf)
end

# => <Elves @name="Sandrine Gorczany", @title="Chief Response Designer">
# => <Elves @name="Jakob Ondricka", @title="National Research Liason">
# => <Elves @name="Kelsi Weimann", @title="Lead Operations Consultant">

On The Seventh Day of Christmas - mail_view

Before you send those letters to Santa, make sure they are perfect with mail_view. Mail_view allows you to preview html and plain text emails in your browser without resending the message. This comes in handy while tweeking your email templates. There are some additional steps when setting up mail_view similar to a mailer unit test. Unlike mailer unit tests you will get the gift of a visual representation.


# app/mailers/mail_preview.rb 
class MailPreview < MailView

  def welcome
    user = User.create!
    mail = Notifier.welcome(user)
    user.destroy
    mail
  end

end

Then add a route for the developement environment.


# config/routes.rb
if Rails.env.development?
  mount MailPreview => 'mail_view'
end

Finally call http://localhost:3000/mail_view to list links to your preview(s).

On The Eighth Day of Christmas - stamp

Is it December 25, 2012 or Dec 25, 12? Either way you can use stamp to format your date with a human-friendly example. Stamp also handles time formatting. It's easy to set up and you can even configure your Rails applications with self-documenting formats.

Once you install the gem, simply pass your human-friendly format:


date = Date.new(2012, 12, 25)
date.stamp("June 25, 2012")  => "December 25, 2012"
date.stamp("Jun 25, 2012")  => "Dec 25, 2012"

Configuring your Rails date formats in an initializer:


Date::DATE_FORMATS[:long] = Proc.new { |date| date.stamp("December 25, 2012") }

On The Nineth Day of Christmas - better_errors

It's hard to stay off the naughty list if you don't know what you're doing wrong but the Rails default error messages can be hard as coal to break. The better_errors replaces the standard Rails error page with a well formatted and useful page. The gem can also be used with your Sinatra app as Rack middleware. In addition to the stack trace and source code inspection, the page can also include local and instance variable inspection as well as live REPL on every stack frame. The advanced features require the binding_of_caller gem. Setup is simply a matter of adding the gem(s) to a development group in your Gemfile.

Here is an example for a Sinatra app with an optional BetterErrors.application_root to abbreviate filenames within an app:


require 'better_errors'

use BetterErrors::Middleware
BetterErrors.application_root = File.expand_path('..', __FILE__)

get '/' do
  raise 'you made the naughty list'
end

On The Tenth Day of Christmas - database_cleaner

Tidying up your database after running tests shouldn't take as long as cleaning up after holiday guests. Cucumber-rails users may be familiar with the little gem database_cleaner which provides strategies for cleaning up databases in Ruby. It was designed to ensure a clean state during tests and it supports several ORMs including ActiveRecord, DataMapper, and Mongoid. Each ORM has a default strategy and some offer alternative options.

If you are using database_cleaner in tandem with cucumber-rails then configuring your strategy is handled in features/support/env.rb:

# features/support/env.rb

begin
  DatabaseCleaner.strategy = :transaction
rescue NameError
  # raise error to add database_cleaner to Gemfile
end

What if you're using a combination of ORMs like ActiveRecord and Mongoid?

# features/support/env.rb

begin
  DatabaseCleaner[:active_record].strategy = :transaction
  DatabaseCleaner[:mongoid].strategy = :truncation
rescue NameError
  # raise error to add database_cleaner to Gemfile
end

With the :truncation strategy you can even limit to specific tables by passing options:


DatabaseCleaner.strategy = :truncation, { only: %w[person place other_table] }


DatabaseCleaner.strategy = :truncation, { except: %w[thing] }

On The Eleventh Day of Christmas - quantum_leap

With all the joy of the holidays wouldn't it be great to freeze time or at least stabilize your test suite? The quantum_leap gem lets you travel in time to revisit those past holidays and fix time wrongs in your tests.


Quantum.leap(Time.new(1985, 12, 25))
johnny.must_be_kind_of(Child)
johnny.must_get_nintendo
Quantum.leap_back

Or with a block:


Quantum.leap(Time.new(1989, 12, 25)) do
  johnny.must_be_kind_of(Child)
  johnny.must_get_sega
end

On The Twelfth Day of Christmas - redcarpet

Forgetting to send out Christmas cards can be a holiday faux pas but forgetting to format them can be down right disatrous. Markdown is a great way to format and the redcarpet gem is perfect for your markdown processing. Redcarpet is an api powered by the C library sundown. The real beauty is in its simplicity.

For basic usage, create a new instance of a Markdown object with a renderer. Then pass the instance the markdown text to render:


markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
markdown.render("## Merry Christmas!")

#=> "<h2>Merry Christmas!</h2>"

As Christmas passes and we look forward to the New Year, we wrap up this present with a thank you! It has been fun sharing these gems with you.

Posted in Development and tagged with Ruby