Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emulate Default Object#inspect Output?

Tags:

ruby

o = Object.new
o.instance_eval { @str = "foo" }
p o # => #<Object:0x5dd1a0 @foo="bar">

This is good. Calling p with an object as an argument prints the output of the objects inspect method. But, unfortunately, if the object has a to_s method overridden then it will output the output of that:

class << o
  def to_s; @str; end
end
p o.to_s # => "foo"
p o # => foo

So to fix this, we have to define an inspect method on our object:

class << o
  def inspect; "blah"; end
end
p o # => "blah"

How would I make my object's inspect method output the default Ruby way as shown in line 3 of my first code example?

The closest I have is the below, but I'm not sure if it's quite right

class << o
  def inspect
    vars = instance_variables.collect { |v| v.to_s << "=#{instance_variable_get(v).inspect}"}.join(", ")
    "#<#{self.class}:0x#{object_id} #{vars}>"
  end
end
like image 980
RyanScottLewis Avatar asked Apr 24 '11 15:04

RyanScottLewis


1 Answers

To make the numbers match the original implementation, you just need to left shift the object_id by one bit which is as shown as follow:

(object_id << 1).to_s(16)

There must be an extra bit used for a flag.

like image 117
Lyle Kopnicky Avatar answered Oct 06 '22 05:10

Lyle Kopnicky