Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find each instance of a class in Ruby

Is there a way to get all the objects that are of a certain class in Ruby?

To clarify:

class Pokemon
end

pikatchu = Pokemon.new
charmander = Pokemon.new

So, is there a way I could somehow retrieve references those two objects (pikatchu and charmander)?

I actually thought of shoving it all into a class array via initialize, but that could potentially grow big, and I am assuming there might be a native Ruby approach to it.

like image 522
omninonsense Avatar asked May 26 '11 21:05

omninonsense


People also ask

How do I know what class an instance is in Ruby?

is_a?(Class_name) method. This method is defined in the Object class of Ruby's library and sorely used for checking the class of a particular object or instance. This method returns Boolean value which are true and false.

What is instance in Ruby?

An instance variable in ruby has a name starting with @ symbol, and its content is restricted to whatever the object itself refers to. Two separate objects, even though they belong to the same class, are allowed to have different values for their instance variables.

What is new () in Ruby?

Creating Objects in Ruby using new Method You can create objects in Ruby by using the method new of the class. The method new is a unique type of method, which is predefined in the Ruby library. The new method belongs to the class methods.


3 Answers

The solution is to use ObjectSpace.each_object method like

ObjectSpace.each_object(Pokemon) {|x| p x}

which produces

<Pokemon:0x0000010098aa70>
<Pokemon:0x00000100992158>
 => 2 

Details are discussed in the PickAxe book Chapter 25

like image 135
Grant Sayer Avatar answered Sep 30 '22 14:09

Grant Sayer


Yes, one could use ObjectSpace, but in practice one would simply keep track of instances as they are created.

class Pokemon
  @pokees = []
  self.class.public_send(:attr_reader, :pokees)

  def initialize
    self.class.pokees << self
  end
end

pikatchu = Pokemon.new
  #=> #<Pokemon:0x00005c46da66d640> 
charmander = Pokemon.new
  #=> #<Pokemon:0x00005c46da4cc7f0> 
Pokemon.pokees
  #=> [#<Pokemon:0x00005c46da66d640>, #<Pokemon:0x00005c46da4cc7f0>] 
like image 23
Cary Swoveland Avatar answered Sep 30 '22 15:09

Cary Swoveland


ObjectSpace is a simple solution, but note that you can only add to it; removing objects requires garbage collection and that can get messy.

Here's an example of tracking class members that allows you to clear the count. This could be useful, for example, when writing a dummy class for specs.

class Foo
  @@instances = []

  def initialize
    @@instances << self
  end

  def self.clear
    @@instances.clear
  end

  def self.all
    @@instances
  end
end

Usage:

(1..10).each { Foo.new }
Foo.all.size # 10
Foo.clear
Foo.all.size # 0
like image 29
Kevin Cooper Avatar answered Sep 30 '22 15:09

Kevin Cooper