2016-07-17 69 views
0

我正在使用Mash.to_module(來自Hashie)將類設置。這工作正常,單元測試我的配置系統,我想能夠重置此類方法。經過5個小時的掙扎之後,我終於找到了一種方法來刪除類方法設置,但是我不能把它放回去......在undef之後還有其他生活方式,或者刪除類方法的另一種方法? this question的解決方案似乎不起作用。我正在使用ruby 2.1.5。如何刪除類方法?

下面是一些測試代碼:

class Mash < Hash 
    def to_module(mash_method_name = :settings) 
     mash = self 
     Module.new do |m| 
     m.send :define_method, mash_method_name.to_sym do 
      mash 
     end 
     end 
    end 
end 

class B 

    class << self 

     def reset 

      # singleton_methods.include? :settings    # true 
      # methods.include? :settings       # true 
      # remove_method :settings       # method `settings' not defined in #<Class:B> 
      # send :remove_method, :settings      # method `settings' not defined in #<Class:B> 
      # singleton_class.remove_method, :settings   # method `settings' not defined in #<Class:B> 

      # B.singleton_methods.include? :settings    # true 
      # B.methods.include? :settings      # true 
      # B.send :remove_method, :settings     # method `settings' not defined in #<Class:B> 
      # B.singleton_class.send :remove_method, :settings # method `settings' not defined in #<Class:B> 

      # methods.include?(:settings) and undef :settings # unexpected keyword undef 
      undef :settings if methods.include?(:settings)  # works 

     end 
    end 

end 

B.extend Mash.new.to_module 
b = B.new 

B.settings # {} 
# b.settings # undefined method `settings' <- intented behaviour 

# B.instance_eval { remove_method :settings } # `remove_method': method `settings' not defined in B 
# B.instance_eval { undef :settings } # WORKS ! 
B.reset 

# B.settings # # undefined method `settings' <- GOOD! 

B.extend Mash.new.to_module 
B.settings # undefined method `settings' => OOPS, is there life after undef? 

回答

1

您的難度不下來的方法是一個類的方法,但由於該方法是一個模塊中定義。首先,您需要明確remove_methodundef_method之間的區別。

remove_method從定義它的類/模塊(即包含相應的def或調用其中的define_method)的類/模塊中刪除方法。如果您嘗試並調用該方法,ruby仍會嘗試搜索超類和包含的模塊。這裏remove_method不適合你,因爲接收者是B的單例類,但是方法沒有在那裏定義(它是在匿名模塊上定義的),因此有關該方法沒有在類上定義的錯誤。

undef_method阻止某個類響應某個方法,而不管該方法是在哪裏定義的。這就是爲什麼在調用undef_method之後擴展一個新模塊不起作用的原因:您已經告訴ruby不要在祖先中搜索該方法。

但是,你可以在你的課程擴展模塊上調用remove_method。這將停止settings正在使用bur將不會干擾,如果類擴展與另一個模塊定義的方法。

+0

謝謝!這有助於我進一步。但是,如果我理解得很好,做你的建議只會影響使用這個模塊的一切,而不僅僅是我試圖影響的課程。 – nus

+0

噢,我明白了,我可以改變模塊以使用'extended(base)'使方法直接在接收器的單例類上定義。 – nus

+0

這會影響所有使用該模塊的人,但是由於您已經介紹過該模塊從未重用過的內容。 –