使用改进来修补核心模块,例如内核

max*_*ner 3 ruby refinements

我正在浏览 Facets API 并选择一些方法来包含在我的细化兼容补丁库中。

我在尝试修补内核时遇到了障碍。它是一个模块,而我修补的其他东西是类(字符串、数组等)


这是不能使用我的核心类标准方法进行改进的证据:

module Patch
  refine Kernel do
    def patched?
      true
    end
  end
end

# TypeError: wrong argument type Module (expected Class)
# from (pry):16:in `refine' 
Run Code Online (Sandbox Code Playgroud)

我还尝试将内核模块包装在一个类中,并将对内核的全局引用更改为该类。

class MyKernel
  include Kernel
  extend Kernel
end

# not sure if Object::Kernel is really the global reference
Object::Kernel = MyKernel

module Patch
  refine MyKernel do
    def patched?
      true
     end
  end
end

class Test
  using Patch
  patched?
end
# NoMethodError: undefined method `patched?' for Test:Class
# from (pry):15:in `<class:Test>'
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我可以通过用对象替换内核来成功获得相同的功能:

module Patch
  refine Object do
    def patched?
      true
     end
  end
end

class Test
  using Patch
  patched?
end
Run Code Online (Sandbox Code Playgroud)

但我不确定是否可以与其他核心模块(例如 Enumerable)获得这种等价性。

cho*_*boy 5

Modules can be refined as of ruby 2.4:

Module#refine accepts a module as the argument now. [Feature #12534]

The old caveat ("Refinements only modify classes, not modules so the argument must be a class") no longer applies (although it wasn't removed from the documentation until ruby 2.6).

Example:

module ModuleRefinement
  refine Enumerable do
    def tally(&block)
      block ||= ->(value) { value }
      counter = Hash.new(0)
      each { |value| counter[block[value]] += 1 }
      counter
    end
  end
end

using ModuleRefinement

p 'banana'.chars.tally # => {"b"=>1, "a"=>3, "n"=>2}
Run Code Online (Sandbox Code Playgroud)