Ruby Language Raffinements dynamiques


Exemple

Les raffinements ont des limitations spéciales.

refine ne peut être utilisé que dans une portée de module, mais peut être programmé en utilisant send :refine .

using est plus limitée. Il ne peut être appelé que dans une définition de classe / module. Cependant, il peut accepter une variable pointant vers un module et être appelé en boucle.

Un exemple montrant ces concepts:

module Patch
  def patched?; true; end
end

Patch.send(:refine, String) { include Patch }

patch_classes = [Patch]

class Patched
  patch_classes.each { |klass| using klass }
  "".patched? # => true
end

Puisque using est si statique, il est possible de générer un ordre de chargement si les fichiers de raffinement ne sont pas chargés en premier. Un moyen de résoudre ce problème consiste à envelopper la définition de classe / module corrigée dans un processus. Par exemple:

module Patch
  refine String do
    def patched; true; end
  end
end

class Foo
end

# This is a proc since methods can't contain class definitions
create_patched_class = Proc.new do
  Foo.class_exec do
    class Bar
      using Patch
      def self.patched?; ''.patched == true; end
    end
  end
end
create_patched_class.call
Foo::Bar.patched? # => true

L'appel du proc crée la classe corrigée Foo::Bar . Cela peut être retardé jusqu'à ce que tout le code ait été chargé.