2012-03-06 15 views
7

私が使用しているレールエンジンの特定のモデルがオブジェクト空間で重複しているという奇妙な問題があります。オブジェクト空間のクラスの複製object_id

(rdb:1) ObjectSpace.each_object(::Class).each { |klass| puts klass.to_s + ": " + klass.object_id.to_s if klass.to_s.eql?("DynamicFieldsets::Field") } 
DynamicFieldsets::Field: 66866100 
DynamicFieldsets::Field: 71836380 
2479 

この場合、is_aは使用できません。オブジェクトがFieldクラスのインスタンスであるかどうかをテストします。この問題は開発時にのみ発生し、cache_classesがオフになっている可能性があります。以前のリクエストのオブジェクトはオブジェクト空間に残っていると思いますが、削除する方法がわかりません。

+1

+1これは不可能です。同じ定数にバインドされた2つのオブジェクトはどのようにありますか? #{klass.inspect}は何を 'puts 'するのですか?#{klass.object_id}" if ... "出力しますか? –

+0

'DynamicFieldsets :: Field'とはどんなソートクラスですか?それはどこから来たのですか? –

+0

DynamicFieldsets :: Fieldは、レールエンジンから来るActiveRecord :: Baseオブジェクトです。オブジェクト空間のクラスを検査するとき、オブジェクトIDを除いてまったく同じです。等しいかどうかをチェックするメソッドは、is_aなど、オブジェクトをチェックするメソッドを除いてtrueを返します。 。 – jeremiahishere

答えて

2

これはremove_constで再現するのは簡単です:

class X 
    def self.foo 
    "hello" 
    end 
end 
first_x = X.new 

Object.send :remove_const, :X 
class X 
    def self.foo 
    "world" 
    end 
end 
second_x = X.new 

p first_x.class, first_x.class.object_id, second_x.class, second_x.class.object_id 
    # => X, <an_id>, X, <another_id> 
p first_x.class.foo, second_x.class.foo 
    # => "hello", "world" 

あなたが述べたように、あなただけの開発にこの症状を取得します。 Railsがクラスをリロードすると、定義されたクラスのremove_constが呼び出され、強制的にリロードされます(autoloadを使用)。 Here's the code。以下のような(それが定義されている場合hereが説明したようにRailsは、実際にこれらのゴミを収集しなければならないとあなたがGC.startでGCをトリガすることができますどのように素敵な:-)

DynamicFieldsets::Field.before_remove_constを呼び出しますが、あなたは転がっ古いクラスのインスタンスを持っている場合私の例ではfirst_x)、またはサブクラスでは、古いクラスはガベージコレクションできません。

is_a?は、新しいインスタンスが新しいクラスのkind_of?is_a?になるという意味で、うまくいくはずです。私の例では:Xは新しいクラスではなく、昔のクラスを指す

first_x.is_a? X # => false 
second_x.is_a? X # => true 

これは、右の動作です。

関連する問題