2016-07-17 68 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

这会影响所有使用该模块的人,但是由于您已经介绍过该模块从未重用过的内容。 –