13

Say I have a class called Post that has many initiated instances (i.e. Post.new(:name => 'foo')).

Is there a way to retrieve all the instances of that class by calling something on it? I'm looking for something along the lines of Post.instances.all

Christopher Oezbek
  • 23,994
  • 6
  • 61
  • 85
Yuval Karmi
  • 26,277
  • 39
  • 124
  • 175
  • 1
    You could probably store a list of reference manually that you update from the constructor... but I'm curious why you would need to do that? – Locksfree Jun 15 '11 at 23:33

3 Answers3

24

You can use ObjectSpace to retrieve all instantiated objects of a given class:

posts = []
ObjectSpace.each_object Post do |post|
  posts << post
end

This is almost certainly a bad idea, though - for example, it will also load Post instances that are still in memory from earlier requests that haven't been garbage-collected. There's probably a much better way to get at the posts you care about, but we'll need more information about what you're trying to do.

Ulysse BN
  • 10,116
  • 7
  • 54
  • 82
PreciousBodilyFluids
  • 11,881
  • 3
  • 37
  • 44
20

Illustrating both alphazero's and PreciousBodilyFluids answers:

class Foo
  @@instance_collector = []
  def initialize
    @@instance_collector << self
    #other stuff
  end
  def self.all_offspring
    @@instance_collector
  end
end

a = Foo.new
b = Foo.new

p Foo.all_offspring  # => [#<Foo:0x886d67c>, #<Foo:0x886d668>]
p ObjectSpace.each_object(Foo).to_a # => [#<Foo:0x886d668>, #<Foo:0x886d67c>] #order is different
Chris Keele
  • 3,364
  • 3
  • 30
  • 52
steenslag
  • 79,051
  • 16
  • 138
  • 171
7

Override new; keep count; expose property.

alphazero
  • 27,094
  • 3
  • 30
  • 26