Search code examples
rubyruby-2.0ruby-2.1ruby-2.2

How to refine module method in Ruby?


You can refine your class with

module RefinedString
  refine String do
    def to_boolean(text)
    !!(text =~ /^(true|t|yes|y|1)$/i)
    end
  end
end

but how to refine module method? This:

module RefinedMath
  refine Math do
    def PI
      22/7
    end
  end
end

raises: TypeError: wrong argument type Module (expected Class)


Solution

  • This piece of code will work:

    module Math
      def self.pi
        puts 'original method'
       end
    end
    
    module RefinementsInside
      refine Math.singleton_class do
        def pi
          puts 'refined method'
        end
      end
    end
    
    module Main
      using RefinementsInside
      Math.pi #=> refined method
    end
    
    Math.pi #=> original method
    

    Explanation:

    Defining a module #method is equivalent to defining an instance method on its #singleton_class.