0

I have a custom class called Thing, and an array of Thing objects, like this:

class Thing
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def to_s
    @name
  end
end

a = []
a << Thing.new("Fred")
a << Thing.new("George")
a << Thing.new("Steve")
a

When I look at the array in irb, I want it to look like this:

[Fred, George, Steve]

rather than this (the object information): [#, #, #]

In other words, I'd like to be able to see to to_s value of each element in the array when I look at the array with irb. Is there a way to do this?

Glenn
  • 436
  • 1
  • 3
  • 12
  • What about this `a.map{|o|o.name} #=> ["Fred", "George", "Steve"]` or `a.map(&:name) #=> ["Fred", "George", "Steve"]`? – Sagar Pandya Jun 01 '17 at 17:35
  • If you want all instances of a class you could write `ObjectSpace.each_object(Thing).map(&:name) #=> ["Fred", "George", "Steve"]`. See [here](https://stackoverflow.com/questions/14318079/how-do-i-list-all-objects-created-from-a-class-in-ruby) for more details. – Sagar Pandya Jun 01 '17 at 17:47

2 Answers2

5

You might want to override #inspect to get a human-readable version of the object:

class Thing
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def inspect
    @name
  end
end

a = []
a << Thing.new("Fred")
a << Thing.new("George")
a << Thing.new("Steve")
a

=> [Fred, George, Steve]
Adam Sheehan
  • 2,122
  • 23
  • 19
1

For what it's worth, irb isn't typically the interface for your code, so it's probably best not to cater too much to how your objects are represented in that narrow context.

You could override inspect, as Adam Sheehan has suggested. This will work with any instance of Thing, which could be desirable or undesirable depending on the rest of your application.

Another option if you only want this representation with this particular collection of objects is to define a custom collection:

class Things < Array
  def inspect
    "[#{ map(&:name).join(', ') }]"
  end
end

a = Things.new
a << Thing.new("Fred")
a << Thing.new("George")
a << Thing.new("Steve")
a

You can also convert your Array into an instance of Things:

a = []
a = Things.new(a)

This is effectively a Decorator.

coreyward
  • 77,547
  • 20
  • 137
  • 166