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.
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:
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 implementingpretty_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