Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
A tiny debugging library for Ruby
Ruby
tree: e6e4718c63

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
spec
.gitignore
.rvmrc
COPYING
Gemfile
README.md
letters.gemspec

README.md

Letters is a little alphabetical library that makes sophisticated debugging easy & fun.

Quick note about Rails: Until I build a Rails-specific gem, I'm changing Letters to patch Object by default. To only patch core classes, require "letters/patch/core". For Rails support, require "letters/patch/rails". Make sure to do this after Bundler.require in application.rb.

For many of us, troubleshooting begins and ends with the print statement. Others recruit the debugger, too. (Maybe you use print statements to look at changes over time but the debugger to focus on a small bit of code.) These tools are good, but they are the lowest level of how we can debug in Ruby. Letters leverages print, the debugger, control transfer, computer beeps, and other side-effects for more well-rounded visibility into code and state.

Installation

If you're using RubyGems, install Letters with:

gem install letters

By default, requiring "letters" monkey-patches Object. It goes without saying that if you're using Letters in an app that has environments, you probably only want to use it in development.

Debugging with letters

With Letters installed, you have a suite of methods available wherever you want them in your code -- at the end of any expression, in the middle of any pipeline. Most of these methods will output some form of information, though there are more sophisticated ones that pass around control of the application.

There are almost 20 Letters methods so far. You can find them in the documentation.

Let's use with the o method as an example. It is one of the most familiar methods. Calling it prints the receiver to STDOUT and returns the receiver:

{ foo: "bar" }.o 
# => { foo: "bar" }
# prints { foo: "bar" }

That's simple enough, but not really useful. Things get interesting when you're in a pipeline:

words.grep(/interesting/).
  map(&:downcase).
  group_by(&:length).
  values_at(5, 10).
  slice(0..2).
  join(", ")

If I want to know the state of your code after lines 3 and 5, all I have to do is add .o to each one:

words.grep(/interesting/).
  map(&:downcase).
  group_by(&:length).o.
  values_at(5, 10).
  slice(0..2).o.
  join(", ")

Because the o method (and nearly every Letters method) returns the original object, introducing it is only ever for side effects -- it won't change the output of your code.

This is significantly easier than breaking apart the pipeline using variable assignment or a hefty tap block.

The o method takes options, too, so you can add a prefix message to the output or choose another output format -- like YAML or pretty print.

The methods

Letter Command Options Description
a Assert :message, :error_class asserts in the context of its receiver or Letters::AssertionError
b Beep causes your terminal to beep
c Callstack :message prints the current callstack
d Debugger passes control to the debugger
d1/d2 Diff :message, :format, :stream prints a diff between first and second receivers
e Empty :message raises a Letters::EmptyError if its receiver is empty
f File :format, :name writes its receiver into a file in a given format
j Jump (&block) executes its block in the context of its receiver
k Kill :max raises Letters::KillError after a maximum number of calls
l Logger :format, :level logs its receivers on the available logger instance
m Mark as tainted (true|false) taints (or untaints) its receiver
n Nil raises a Letters::NilError if its receiver is nil
o Output :format, :stream prints its receiver to standard output
r Ri (method name as symbol) prints RI documentation of its receiver class
s Safety (level number) bumps the safety level (by one or as specified)
t Timestamp :time_format prints out the current timestamp

See the full documentation for examples and more detailed explanations.

Configuration

Lastly, you can tune and tweak each Letters method to default to your own tastes. Want to name put files somewhere else? No problem. Don't like YAML? Default f to use Pretty Print instead! The world of defaults is your oyster.

Letters.config do
  f :format => "pp", :name => "my-special-file"
end
Something went wrong with that request. Please try again.