Ruby
Hashrocket's 12 Gems of Christmas
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.