classe de carga / descarga / atualização em ruby

Eu fiz um pequeno experimento com carga / descarga / atualização dinâmica da classe Ruby como implementação de infraestrutura de plugins. Eu encontrei alguns pontos:

Se estiver carregando uma nova versão da mesma classe sem primeiro descarregá-la, a nova essencialmente 'top' ou 'merge' com a versão anterior. Todos os objetos existentes criados com a versão anterior teriam sua definição de classe 'atualizada'.O descarregamento de uma classe não afeta objetos existentes criados com essa classe. Objetos existentes ficam com qualquer versão que acabou de ser descarregada. (a classe não pode mais ser usada, mas não os objetos já criados)Se carregando nova versão após o descarregamento da versão anterior, novos objetos criados seriam da nova versão. No entanto, os objetos antigos criados antes do carregamento da nova versão não seriam afetados e ainda seriam da versão antiga.

A minha pergunta é, existe uma maneira fácil de fazer objeto existente criado a partir da versão de classe antiga 'switch' para a nova versão (mas não uma versão mesclada da versão antiga e nova)? Parece-me que a maneira possível de fazer isso é recriar o objeto após o descarregamento / carregamento, o que não é adequado para plugins (não quero que ele seja destruído).

Atualizar: minha intenção era ter objetos existentes atualizados com nova versão, sem o problema de mesclar a versão antiga com a nova versão (como a alteração do número de argumentos ou a remoção de um método). Descarregar e recarregar novamente parece ser a maneira mais limpa de fazer isso, embora você deva manter o controle de todos esses objetos e recriá-los quando necessário. Além disso, objetos caros podem não ser adequados para a recriação. Isso me deixa com a segunda opção, proibindo a fusão inesperada. Contanto que nenhum método seja removido, nenhuma assinatura de método seja alterada, a mesclagem deve funcionar bem.

Abaixo está o meu programa de teste:

$ cat test.rb
load 'v1.rb'
puts "=> 'v1.rb' loaded"
a1 = A.new
puts "=> object a1(#{a1}) created"
a1.common
a1.method_v1
load 'v2.rb'
puts '',"=> class A updated by 'v2.rb'"
a1.common
a1.method_v1
a1.method_v2

a2 = A.new
puts '',"=> object a2(#{a2}) created"
a2.common
a2.method_v1
a2.method_v2

Object.send(:remove_const, 'A')
puts '',"=> class A unloaded"

A.new rescue puts $!

puts '',"=> class A does not exist now"
a1.common
a1.method_v1
a1.method_v2 rescue puts $!
a2.common
a2.method_v1
a2.method_v2

load 'v3.rb'
puts '',"=> 'v3.rb' loaded"
a1.common
a1.method_v1
a1.method_v2 rescue puts $!
a1.method_v3 rescue puts $!
a2.common
a2.method_v1
a2.method_v2
a2.method_v3 rescue puts $!

a3 = A.new
puts '',"=> object a3(#{a3}) create"
a3.common
a3.method_v1 rescue puts $!
a3.method_v2 rescue puts $!
a3.method_v3

A saída da amostra:

$ ruby test.rb
=> 'v1.rb' loaded
=> object a1(#<A:0x1042d4b0>) created
#<A:0x1042d4b0>: common: v1
#<A:0x1042d4b0>: method v1

=> class A updated by 'v2.rb'
#<A:0x1042d4b0>: common: v2
#<A:0x1042d4b0>: method v1
#<A:0x1042d4b0>: method v2

=> object a2(#<A:0x1042cec0>) created
#<A:0x1042cec0>: common: v2
#<A:0x1042cec0>: method v1
#<A:0x1042cec0>: method v2

=> class A unloaded
uninitialized constant A

=> class A does not exist now
#<A:0x1042d4b0>: common: v2
#<A:0x1042d4b0>: method v1
#<A:0x1042d4b0>: method v2
#<A:0x1042cec0>: common: v2
#<A:0x1042cec0>: method v1
#<A:0x1042cec0>: method v2

=> 'v3.rb' loaded
#<A:0x1042d4b0>: common: v2
#<A:0x1042d4b0>: method v1
#<A:0x1042d4b0>: method v2
undefined method `method_v3' for #<A:0x1042d4b0>
#<A:0x1042cec0>: common: v2
#<A:0x1042cec0>: method v1
#<A:0x1042cec0>: method v2
undefined method `method_v3' for #<A:0x1042cec0>

=> object a3(#<A:0x1042c3f8>) create
#<A:0x1042c3f8>: common: v3
undefined method `method_v1' for #<A:0x1042c3f8>
undefined method `method_v2' for #<A:0x1042c3f8>
#<A:0x1042c3f8>: method v3

Abaixo estão as 3 versões da classe A:

$ cat v1.rb
class A
  def common
    puts "#{self}: common: v1"
  end
  def method_v1
    puts "#{self}: method v1"
  end
end

$ cat v2.rb
class A
  def common
    puts "#{self}: common: v2"
  end
  def method_v2
    puts "#{self}: method v2"
  end
end

$ cat v3.rb
class A
  def common
    puts "#{self}: common: v3"
  end
  def method_v3
    puts "#{self}: method v3"
  end
end

questionAnswers(2)

yourAnswerToTheQuestion