1
class Person
  attr_accessor :name

  def initialize(name)
     @@name = name
     people.push($)
  end
end

It doesn't have to be in the initialize function. I just want an array of all Persons created.

p1 = Person.new("joe")
p2 = Person.new("rick")
people.inspect #-->would return [p1, p2]

3 Answers 3

4

If you just want a list of all instances of Person, you do not need to add them at creation. Just access them by:

ObjectSpace.each_object(Person).to_a
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for teaching noobs each_object. But I must warn against the approach you demonstrate here - it is not usable with eg. parametrized subclassing.
2

@sawa's answer is the best, since it does not prevent garbage collection. If you do want to record each instance as it is created (and prevent garbage collection of otherwise-unused instances) you can simply:

class Person
  @all = []
  def self.all; @all; end
  attr_accessor :name
  def initialize(name)
    @name = name
    self.class.all << self
  end
end

p1 = Person.new("joe")
p2 = Person.new("rick")
p Person.all
#=> [#<Person:0x007f9d1c8c4838 @name="joe">,
#=>  #<Person:0x007f9d1c8bb0d0 @name="rick">]

3 Comments

Can you explain a little what do you mean by saying "it does not prevent garbage collection"?
And for completeness, I would say that even @Frog's answer allows for garbage collection, if the class itself is garbage collected at due time – I'm talking about parametrized subclassing, where an anonymous subclass of Person is stored in some container object and used to construct Person instances pertaining to that container. Once the container is gone, or ceases to have need for its Persons, parametrized subclass itself is discarded and all the instances are subsequently GC-ed, because the array that refers to them and belongs to the subclass disappears.
@YuanhangGuo Imagine this code: def ghost; p Person.new("nobody"); end. Calling this method creates a new Person instance and then, when the method is exited, that person is no longer needed. Without my code above, you could call this method 10,000,000 times without a memory problem, because each instance would be garbage collected eventually. However, with my code above a reference is kept to each and every instance in the @all array, and thus they may never be taken out of memory.
1

And I, mandatorily, will introduce my NameMagic here:

# first, gem install y_support
require 'y_support/name_magic'

class Person
  include NameMagic
  # here, Person receives for free the following functionality:
  # * ability to use :name (alias :ɴ) named argument in the constructor
  # * #name (alias #ɴ) instance method
  # * #name= naming / renaming method
  # * ability to name anonymous instances by merely assigning to constants
  # * collection of both named and anonymous instances inside the namespace
  # * hooks to modify the name, or do something else when the name is assigned
  # * ability to specify a different namespace than mother class for instance collection
end

Joe = Person.new #=> #<Person:0xb7ca89f8>
Rick = Person.new #=> #<Person:0xb7ca57bc>

Joe.name #=> :Joe
Rick.ɴ #=> :Rick
Person.instances # [#<Person:0xb7ca89f8>, #<Person:0xb7ca57bc>]
Person.instance_names # [:Joe, :Rick]

Person.new name: "Kit" #=> #<Person:0xb9776244>
Person.instance_names #=> [:Joe, :Rick, :Kit]
p3 = Person.instance( :Kit ) #=> #<Person:0xb9776244>
p2 = Person.instance( "Rick" ) #=> #<Person:0xb7ca57bc>
# Also works if the argument is already a Person instance:
p1 = Person.instance( Person.instance( :Joe ) ) #=> #<Person:0xb9515ba8>

anon = Person.new #=> #<Person:0xb9955c54>
Person.instances.size #=> 4
Person.instance_names #=> [:Joe, :Rick, :Kit]
anon.name = :Hugo
Person.instance_names #=> [:Joe, :Rick, :Kit, :Hugo]
Person::Hugo #=> #<Person:0xb9955c54>

For concerns about garbage collection, one can forget the instances

Person.forget :Hugo #=> Returns, for the last time, "Hugo" instance
Person::Hugo #=> NameError
Person.forget_all_instances #=> [:Joe, :Rick, :Kit]
Person.instances #=> [] - everything is free to be GCed

Under the hood NameMagic uses the same approach as @sawa proposed (at least until const_assigned hook is provided by Ruby core devs), that is, searching whole ObjectSpace – but not for the instances of the mother object, but for the namespaces (Module class objects), whose constants are searched for the unnamed instances being assigned to them.

3 Comments

I like the .instance_names - I'd rather not install more gems. Is there a way to access Person where name = 'rick' without this gem?
I can understand your feelings. Having too many dependencies is bad. The unique thing that this gem provides is the ability to name objects by assignment to constants: Rick = Person.new. All else is just regular ordinary Ruby coding. Feel free to simply copy & paste the code to your project.
@user1541542: But I can assure you that I'm working hard to make this gem maintained by a reliable group of people, and I also assure you, that every single Rubyists needs this precise functionality now and then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.