How to enable pretty IRB inspection for your Ruby class

Posted . Visible to the public.

When Ruby objects are inspected in any modern IRB, some objects (like ActiveRecord instances) are rendered with neat colors and line breaks.
You will not get that for custom classes by default -- which can be annoying if your inspection contains lots of meaningful information.

Here is what you need to do if you want your objects to be inspected nicely.

Implement a pretty_print method

As an example, consider the following class.

class MyClass

  # ...

  def inspect
    "#<#{self.class} attr1: #{attr1.inspect}, attr2: #{attr2.inspect}>"
  end
  
end

Instances of that class will inspect like #<MyClass attr1: "Alice", attr2: "Bob">, but IRB will apply a single color (green) for everything.

Inspection with inspect

That is because MyClass implements only inspect. If it were to implement pretty_print, IRB would use that for inspection.
Note that this requires the PP class from the pp gem. It is loaded in any Rails app already, but for plain Ruby you may need to require it.

Here is an example implementation for our class above:

require 'pp'

class MyClass

  # ...

  def inspect
    inspections = inspections_tuples.map { |tuple| tuple.join(": ") }
    "#<#{self.class} #{inspections.join(', ')}>"
  end
  
  def pretty_print(pp)
    pp.object_address_group(self) do
      pp.seplist(inspections_tuples, proc { pp.text "," }) do |(name, value)|
        pp.breakable " "
        pp.group(1) do
          pp.text name
          pp.text ":"
          pp.breakable
          pp.text value
        end
      end
    end
  end
  
  private
  
  def inspections_tuples
    [
      ["attr1", attr1.inspect],
      ["attr2", attr2.inspect]
    ]
  end

end

Your objects are now inspected with pretty colors:

Inspection with pretty_print

Note that if your inspection becomes wider than your terminal, IRB will automatically break it across multiple lines, like you probably know from more complex ActiveRecord instances.

Note

Generally, you should definitely implement inspect for any non-trivial custom classes.
If you inspection is simple enough, I suggest not implementing pretty_print, as it can negatively impact code readability.

As a fallback: Implement a pretty_inspect method

While you're at it, you may want to add a custom pretty_inspect as well. It's fairly simple to do and can serve as a fallback if pretty-printing is not applicable.

This can also be an alternative if defining pretty_print feels like too much code for you.

class MyClass

  # ...

  def inspect
    inspections = inspections_tuples.map { |tuple| tuple.join(": ") }
    "#<#{self.class} #{inspections.join(', ')}>"
  end
  
  def pretty_inspect
    inspections = inspections_tuples.map { |tuple| tuple.join(": ") }
    "#<#{self.class}\n #{inspections.join(",\n ")}>"
  end
  
  # ...
  
end

Inspection with pretty_inspect

Arne Hartherz
Last edit
Arne Hartherz
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2024-11-27 08:27)