# safer monkey patch ###### tags: `advanced ruby` ruby class 裡的method會融合,不論何時new ```ruby= class Human def initialize end end person = Human.new # monkey patch class Human def age puts 'not young' end end person.age # => not young ``` - 想做個時間單位換秒數 `2.hours` `3.days` ```ruby= 2.class # => Integer ``` ```ruby= class Integer def minutes 60 * self end def hours 60 * minutes end def days 24 * hours end end puts 2.minutes puts 3.hours # => 120 # => 10800 ``` - 會覆寫require來的methods: ```ruby= require 'active_support/all' class Integer def minutes 60 * self end def hours 60 * minutes end def days 24 * hours end end puts 3.hours.ago # => undefined method `ago' for 10800:Integer (NoMethodError) puts 3.hours.class # => Integer ``` 如何避免: - `refine`定義monkey patch - `using` 引入 ```ruby= # 使用refine避免大範圍污染同名methods # refine必須包在module內 require 'active_support/all' module GetSeconds refine Integer do def minutes 60 * self end def hours 60 * minutes end def days 24 * hours end end end puts 3.hours.class # => ActiveSupport::Duration # 用using引入refine # 僅有使用using的class才會被monkey patch class MyPatch using GetSeconds def demo 3.hours end end my_patch = MyPatch.new puts my_patch.demo # => 10800 puts my_patch.demo.class # => Integer ``` - 原則上避免monkey patch - 若要monkey patch,請使用`refine`,並用`using`引入 ref: [Refinements](https://docs.ruby-lang.org/en/2.4.0/syntax/refinements_rdoc.html)