수색…


비고

상세 검색은 어휘 적으로 범위가 있습니다. 즉, 컨트롤이 바뀔 때까지 활성화 키워드 ( using 키워드 using )부터 적용됩니다. 일반적으로 제어는 모듈, 클래스 또는 파일의 끝으로 변경됩니다.

제한된 범위의 원숭이 패치

Monkey patching의 주요한 문제점은 그것이 글로벌 범위를 오염 시킨다는 것입니다. 코드 작업은 서로 다른 발가락을 밟지 않고 사용하는 모든 모듈을 자비로 사용합니다. 이것에 대한 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