Comment puis-je lister tous les objets créés à partir d'une classe de Ruby? [dupliquer]

cette question a déjà une réponse ici:

y a-t-il un moyen dans Ruby pour qu'une classe sache combien de cas il existe et peut-elle les énumérer?

Voici une classe d'échantillon:

class Project

  attr_accessor :name, :tasks

  def initialize(options)
    @name = options[:name]
    @tasks = options[:tasks]
  end

  def self.all
    # return listing of project objects
  end

    def self.count
          # return a count of existing projects
    end


end

maintenant je crée des objets de projet de cette classe:

options1 = {
  name: 'Building house',
  priority: 2,
  tasks: []
}

options2 = {
  name: 'Getting a loan from the Bank',
  priority: 3,
  tasks: []
}

@project1 = Project.new(options1)
@project2 = Project.new(options2)

ce que je voudrais c'est avoir des méthodes de classe comme Project.all et Project.count pour retourner une liste et un compte de projets en cours.

Comment faire?

29
demandé sur the Tin Man 2013-01-14 16:02:38

4 réponses

vous pouvez utiliser le module ObjectSpace pour ce faire, en particulier la méthode each_object .

ObjectSpace.each_object(Project).count

Pour être complet, voici comment vous pourriez utiliser dans votre classe (hat tip pour sawa)

class Project
  # ...

  def self.all
    ObjectSpace.each_object(self).to_a
  end

  def self.count
    all.count
  end
end
42
répondu Andrew Haines 2013-01-14 13:35:30

une façon de le faire est de garder une trace au fur et à mesure que vous créez de nouvelles instances.

class Project

    @@count = 0
    @@instances = []

    def initialize(options)
           @@count += 1
           @@instances << self
    end

    def self.all
        @@instances.inspect
    end

    def self.count
        @@count
    end

end

Si vous voulez utiliser ObjectSpace , puis son

def self.count
    ObjectSpace.each_object(self).count
end

def self.all
    ObjectSpace.each_object(self).to_a
end
5
répondu rohit89 2013-01-14 13:32:31
class Project
    def self.all; ObjectSpace.each_object(self).to_a end
    def self.count; all.length end
end
4
répondu sawa 2013-01-14 12:50:56

peut-être que ça marchera:

class Project
  class << self; attr_accessor :instances; end

  attr_accessor :name, :tasks

  def initialize(options)
    @name = options[:name]
    @tasks = options[:tasks]

    self.class.instances ||= Array.new
    self.class.instances << self
  end

  def self.all
    # return listing of project objects
    instances ? instances.dup : []
  end

  def self.count
    # return a count of existing projects
    instances ? instances.count : 0 
  end

  def destroy
    self.class.instances.delete(self)
  end
end

mais vous devrez détruire manuellement ces objets. Peut-être que d'autres solutions peuvent être construites sur la base du module ObjectSpace.

2
répondu yattering 2013-01-14 12:29:02