简体   繁体   English

在对象空间object_id中复制类

[英]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. 我有一个奇怪的问题,我正在使用的rails引擎中的某些模型在对象空间中被复制。

(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? 发生这种情况时,我不能使用is_a? or equality checks to test that an object is an instance of the Field class. 或等式检查以测试对象是Field类的实例。 The problem only happens in development and it looks like it may be caused by cache_classes being off. 问题只发生在开发中,看起来它可能是由cache_classes关闭引起的。 I think the object from the previous request is still in the object space but I am not sure how to remove it. 我认为前一个请求中的对象仍然在对象空间中,但我不知道如何删除它。

This is easy to reproduce with remove_const : 使用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 ). 当Rails重新加载类时,它只是在定义的类上调用remove_const ,强制它们被重新加载(使用autoload )。 Here's the code . 这是代码 Rails will actually call DynamicFieldsets::Field.before_remove_const if it is defined, as explained here , how nice :-) Rails会实际调用DynamicFieldsets::Field.before_remove_const如果它被定义为解释在这里 ,:-)真好

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. 这些应该是垃圾收集的,您可以使用GC.start触发GC,但如果您有旧类的实例(例如我的示例中的first_x )或子类,则旧类不能被垃圾收集。

Note that is_a? 注意is_a? should work fine, in the sense that new instances will be kind_of? 应该工作得很好,因为新的实例将是kind_of? and is_a? 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. 这是正确的行为,因为X指的是新类,而不是旧类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM