Дублирование класса в объектном пространстве object_id - PullRequest
7 голосов
/ 07 марта 2012

У меня странная проблема, когда определенные модели в движке рельсов, который я использую, дублируются в пространстве объектов.

(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. Я думаю, что объект из предыдущего запроса все еще находится в пространстве объектов, но я не уверен, как его удалить.

1 Ответ

2 голосов
/ 11 марта 2012

Это легко воспроизвести с помощью 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). Вот код . На самом деле Rails будет вызывать DynamicFieldsets::Field.before_remove_const, если он определен, как объяснено здесь , как хорошо: -)

Это должен быть сборщик мусора, и вы можете запустить GC с помощью GC.start, но если у вас есть экземпляры старых классов (например, first_x в моем примере) или подклассов, старые классы не могут быть мусором собраны.

Обратите внимание, что is_a? должно работать нормально, в том смысле, что новые экземпляры будут kind_of? и is_a? нового класса. В моем примере:

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

Это правильное поведение, поскольку X относится к новому классу, а не к старому классу.

...