ruby-on-rails - 在对象空间 object_id 中复制类

标签 ruby-on-rails ruby gem rails-engines

我遇到一个奇怪的问题,我正在使用的 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 被关闭引起的。我认为之前请求的对象仍在对象空间中,但我不确定如何删除它。

最佳答案

这很容易用 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 指的是新类,而不是旧类。

关于ruby-on-rails - 在对象空间 object_id 中复制类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9592192/

相关文章:

ruby-on-rails - 为什么 config.cache_classes = false 不工作?

ruby-on-rails - 调用 attr_accessible 时出现 MassAssignmentSecurity 错误

ruby - Gem 中的配置 block

ruby - Rails 3 runner 没有检测到 JSON gem?

ruby-on-rails - rails 未初始化常量 Sprockets::SassCacheStore

ruby-on-rails - 为 Rails 3 中的现有数据库模式自动生成脚手架

javascript - 使用 Minitest 在 Rails 应用程序中测试 Javascript

ruby-on-rails - 从 Heroku 上的列表中删除应用程序

ruby-on-rails - Create_table 方法/ block

ruby-on-rails - 您已经激活了 rspec-support 3.0.0.beta1,但是您的 Gemfile 需要 rspec-support 3.0.0.beta1