Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicating class in the object space object_id

I having a strange issue where certain models in a rails engine I am using are getting duplicated in the 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 cannot use is_a? or equality checks to test that an object is an instance of the Field class. The problem only happens in development and it looks like it may be caused by cache_classes being off. I think the object from the previous request is still in the object space but I am not sure how to remove it.

like image 805
jeremiahishere Avatar asked Mar 06 '12 21:03

jeremiahishere


1 Answers

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 stated, you get this symptom only in development. When Rails reloads the classes, it simply calls remove_const on the defined classes, to force them to be reloaded (using autoload). Here's the code. Rails will actually call DynamicFieldsets::Field.before_remove_const if it is defined, as explained here, how nice :-)

These should be garbage collected and you can trigger the GC with GC.start, but if you have instances of the old classes lying around (like first_x in my example), or subclasses, the old classes can not be garbage collected.

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

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

This is the right behavior, as X refers to the new class, not the old class.

like image 125
Marc-André Lafortune Avatar answered Nov 10 '22 03:11

Marc-André Lafortune