我有一个奇怪的问题,我正在使用的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
发生这种情况时,我不能使用is_a?或等式检查以测试对象是Field类的实例。问题只发生在开发中,看起来它可能是由cache_classes关闭引起的。我认为上一个请求中的对象仍然在对象空间中,但我不确定如何删除它。
答案 0 :(得分: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。如果已定义,Rails实际上会调用DynamicFieldsets::Field.before_remove_const
,如here所述,有多好: - )
这些应该是垃圾收集的,您可以使用GC.start
触发GC,但如果您有旧类的实例(例如我的示例中的first_x
)或子类,则旧类不能垃圾收集。
请注意,is_a?
应该可以正常工作,因为新实例将是新类的kind_of?
和is_a?
。在我的例子中:
first_x.is_a? X # => false
second_x.is_a? X # => true
这是正确的行为,因为X
指的是新类,而不是旧类。