2013-01-14 6 views
27

Rubyではクラスのインスタンスがいくつあるのかを知る方法はありますか?ここでRubyでクラスから作成されたすべてのオブジェクトを一覧表示するにはどうすればよいですか?

は、サンプルクラスです:

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 

今、私はこのクラスのプロジェクトのオブジェクトを作成します。私が望む何

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) 

をリストを返すようにProject.allProject.countのようなクラスメソッドを持つことです現在のプロジェクト数。

どうすればよいですか?

答えて

40

ObjectSpaceモジュールを使用すると、具体的にはeach_objectメソッドを使用できます。

ObjectSpace.each_object(Project).count 

は完全を期すため、ここでは、これは私がやるだろうと何である

class Project 
    # ... 

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

    def self.count 
    all.count 
    end 
end 
+0

これを動作させるには、クラスに 'ObjectSpace'をインクルードする必要がありますか? – onebree

+2

@HunterStevensいいえ、私たちのクラスにモジュールを混ぜているわけではなく、メソッドを呼び出すだけです –

+0

**警告**:この解決法は、足で自分自身を簡単に撃つことができます。オブジェクトへの参照を保持していない場合(例えば、何かに結果を代入せずに 'Project.new'を実行した場合)、それらはある時点でガベージコレクションされ、' ObjectSpace.each_object'は明らかにそれらの報告を停止します。 rohit89の答えのように '@ @ instances = []'を使うと、これらのオブジェクトへの参照を保持することでこの問題を解決できます。 – vmarquet

5

1つの方法は、新しいインスタンスを作成するときとそれを記録することです。

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 

あなたがObjectSpaceを使用する場合は、その

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

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

(沢に帽子の先端)は、そのクラス内を使用する方法です。 Rubyのすべての実装で確実に機能し、必要に応じてさまざまな目的に拡張できます。 –

2

は多分これは動作します:

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 

しかし、あなたは手動でこれらのオブジェクトを破壊する必要があります。おそらく、ObjectSpaceモジュールに基づいて他のソリューションを構築することもできます。

+0

私はこれが好きですが、いくつかの反射に組み込まれている必要があります - ルビーには存在しませんか?私はObjectSpaceモジュールの使い方を知りません。例が本当に助けるだろう –

+1

まあ。 ObjectSpaceではガベージコレクタと対話できます。これは自分のコードでやりたくないものです。 'ObjectSpace.each_object(Project).to_a'で試してみることができますが、これ以上これ以上お手伝いできません。 – yattering

+0

これを回避すべき理由は何ですか? –

4
class Project 
    def self.all; ObjectSpace.each_object(self).to_a end 
    def self.count; all.length end 
end 
関連する問題