Duplicating a class in the object_id object space

I have a strange problem when some models in the rails engine that I use are duplicated in object space.

(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 

When this happens, I can not use is_a? or equality checks to verify that the object is an instance of the Field class. The problem only occurs during development, and it looks like it could be caused by disabling cache_classes. I think the object from the previous request is still in the object space, but I'm not sure how to delete it.

+7
source share
1 answer

This is easy to reproduce with 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" 

As you said, you get this symptom only in development. When Rails reloads classes, it simply calls remove_const for specific classes to force them to reload (using autoload ). Here is the code . Rails will actually call DynamicFieldsets::Field.before_remove_const if it is defined as described here , as well DynamicFieldsets::Field.before_remove_const

It should be garbage collection, and you can start GC with GC.start , but if you have instances of the old classes lying around (for example, first_x in my example) or subclasses, the old classes cannot be garbage collected.

Please note that is_a? should work fine, in the sense that new instances will be kind_of? and is_a? new class. In my example:

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

This is the correct behavior, since X belongs to the new class, and not to the old class.

+2
source

All Articles