サーチ…


備考

絞り込みは範囲が語彙的であり、制御が移行するまで有効になってから(キーワードusing )有効であることを意味します。通常、制御はモジュール、クラス、またはファイルの最後で変更されます。

限られた範囲で猿のパッチを当てる

モンキーパッチの主な問題は、グローバルスコープを汚染することです。あなたのコードの作業は、お互いのつま先で足を踏み入れることなく、あなたが使用しているすべてのモジュールの慈悲にあります。これに対するRubyの解決策は洗練されたものであり、基本的には限られた範囲にあるサルのパッチです。

module Patches
  refine Fixnum do
    def plus_one
      self + 1
    end

    def plus(num)
      self + num
    end

    def concat_one
      self.to_s + '1'
    end
  end
end

class RefinementTest
  # has access to our patches
  using Patches

  def initialize
    puts 1.plus_one
    puts 3.concat_one
  end
end

# Main scope doesn't have changes

1.plus_one
# => undefined method `plus_one' for 1:Fixnum (NoMethodError)

RefinementTest.new
# => 2
# => '31'

デュアルパーパスモジュール(リファインメントまたはグローバルパッチ)

洗練された方法でパッチを適用するのは良い習慣ですが、開発やテストなどでグローバルに読み込むのが良いこともあります。

たとえば、コンソールを起動し、ライブラリを必要とし、パッチ適用されたメソッドをグローバルスコープで使用したいとします。クラス/モジュール定義でusingする必要があるため、これを洗練されたものではできません。しかし、それは二重目的のような方法でコードを書くことが可能です:

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

# globally
String.include Patch
"".patched? # => true

# refinement
class LoadPatch
  using Patch
  "".patched? # => true
end

動的リファインメント

精緻化には特別な制限があります。

refineはモジュールスコープでのみ使用できますが、 send :refineを使用してプログラムできます。

usingはより制限されています。クラス/モジュール定義でのみ呼び出すことができます。それでも、モジュールを指す変数を受け入れることができ、ループ内で呼び出すことができます。

これらの概念を示す例:

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

usingは静的なので、詳細ファイルが最初にロードされないと、ロード順で発行されます。これに対処する方法は、パッチされたクラス/モジュール定義をprocにラップすることです。例えば:

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

procを呼び出すと、パッチされたクラスFoo::Barが作成されます。これは、すべてのコードがロードされるまで遅延させることができます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow