Last week, I worked on making the Riak CRDTs print out nicer in the Riak Ruby client. Since my main interaction with riak-client is through the pry REPL and RSpec, I decided to use the pp stdlib library to make the output nicer.

ugly irb output

Out of the box, a Riak CRDT set looked like:

#<Riak::Crdt::Set:0x007fbec39d87b0 @bucket=#<Riak::Bucket {bucketname},
  @key="cats", @bucket_type="sets", @options={}, @dirty=true>

This was terrible for several reasons: the actual value of the set wasn’t listed, the object_id is a ridiculous thing, and the bucket type/bucket/key relationship is hard to read. The end goal was something that made it easy to identify which object was which, what it contained, and elide unimportant implementation details.

Ruby’s pp library has some sensible defaults: print out the class name, object_id, and all instance variables. It’s relatively good for objects built out of primitives, but tends to break down on deep data structures. The CRDTs for Riak tend to be deeply-nested, especially the Map type, which can contain Counters, Flags, Maps (which can continue recursing down), Registers, and Sets.

PP Callbacks

The way PP works is a bit convoluted.

  1. You call pp some_object
  2. Kernel.pp calls PP.pp some_object
  3. PP.pp instantiates a PP instance, and calls PP#pp some_object
  4. PP#pp calls some_object.pretty_print self or some_object.pretty_print_cycle self

Working with PP on your own objects isn’t convoluted: create a pretty_print method that takes a PP instance as its only argument, and calls methods on the instance to output what your users need.

In the case of a recursion, you don’t simply want to repeat the same full representation every time, just enough to know that there’s some recursion.

PP Methods

I ended up using very few methods on PP:

  • object_group wraps its contents with angle brackets and general object information
  • breakable inserts a space that can be used as a line break
  • comma_breakable inserts a comma followed by a breakable space
  • text inserts text
  • pp recursively pretty-prints the given value

Examples

On Riak::Crdt::Base, I wanted to provide the basics that Counter, Map, and Set can inherit from. This method prints out the given class, its bucket type, bucket, key, and then yields to the child class:

# on Riak::Crdt::Base
def pretty_print(pp) pp.object_group self do pp.breakable pp.text "bucket_type=#{@bucket_type}" pp.comma_breakable pp.text "bucket=#{@bucket.name}" pp.comma_breakable pp.text "key=#{@key}" yield end end

On Riak::Crdt::Map, which inherits from Base above, I wrap map-specific fields in the above method. Since it has five sub-collections, I loop over those to pretty-print them individually.

# on Riak::Crdt::Map
def pretty_print(pp)
  super pp do
    %w{counters flags maps registers sets}.each do |h|
      pp.comma_breakable
      pp.text "#{h}="
      pp.pp send h
    end
  end
end

Riak::Crdt::InnerMap doesn’t have a bucket type, bucket, or key. It’s a simple version of what Map does:

# on Riak::Crdt::InnerMap
def pretty_print(pp)
  pp.object_group self do
    %w{counters flags maps registers sets}.each do |h|
      pp.comma_breakable
      pp.text "#{h}="
      pp.pp send h
    end
  end
end

Conclusions

a nicer, colorized pretty-printed map

Pretty-printing is really nice for debugging and playing with Ruby in a REPL. On top of adding pretty-print support to your code, maybe also encourage users to use Pry, which does a great job of colorizing output.