【问题标题】:Monkey patch method on single object单个对象上的猴子补丁方法
【发布时间】:2015-08-19 14:47:42
【问题描述】:

我想在模型类的单个实例上覆盖update_attributes 方法的行为。假设变量被称为@alert 最好的方法是什么?明确地说,我不想为整个类修改此方法的行为。


免责声明:

我需要这样做来强制该方法在我想要的时候返回false,这样我就可以为下面的错误处理代码编写单元测试。我知道这可能不是最佳做法。

【问题讨论】:

  • 我正要更正您对“猴子补丁”一词的使用——认为它仅适用于对 Ruby 内置方法的修改——但在谷歌上搜索后似乎对其没有达成共识意义。例如,请参阅this SO question
  • @CarySwoveland 从历史上看,“钱补丁”是指用你自己的实现来踩踏现有方法,这些方法完全接管。在这种情况下,它更像是一个“模拟”操作,它只改变一个对象,而其他对象,无论是现有的还是未来创建的,都不受影响。
  • 这闻起来很像方法存根,任何体面的测试框架都可以容纳。

标签: ruby-on-rails ruby monkeypatching


【解决方案1】:

只需在对象上定义一个方法:

class Thing
  def greeting
    'yo, man'
  end
end

Thing.instance_methods(false)
  #=> [:greeting]

object = Thing.new
  #=> #<Thing:0x007fc4ba276c90> 

object.greeting
  #=> "yo, man" 

object 上定义两个方法(这将是object 的单例类中的实例方法。

def object.greeting
  'hey, dude'
end

def object.farewell
  'see ya'
end

object.methods(false)
  #=> [:greeting, :farewell] 
object.singleton_class.instance_methods(false) #=> [:greeting, :farewell]

object.greeting
  #=> "hey, dude" 
object.farewell
  #=> "see ya"

new_obj = Thing.new
new_obj.greeting
  #=> "yo, man"
new_obj.farewell
  #NoMethodError: undefined method `farewell' for #<Thing:0x007fe5a406f590>

移除object的单例方法greeting

object.singleton_class.send(:remove_method, :greeting)

object.methods(false)
  #=> [:farewell] 
object.greeting
  #=> "yo, man"

object 的单例类中删除:greeting 的另一种方法如下。

class << object
  remove_method(:greeting)
end

【讨论】:

  • 有时这可以通过制作一个模块并将其混合到单个对象中来更干净地完成。
  • 错字:Thing.new hi 应该是 Thing.new.hi。然后异常将是 NoMethodError: undefined method `hi' for #&lt;Thing:0x000000.......&gt; 而不是 NameError: ...
【解决方案2】:

创建对象后,在其上调用“define_method”:

object = Thing.new
object.define_method("update_attributes") { return false }

完成后,object.update_attributes 现在应该返回 false

【讨论】:

  • 该对象继承自ActiveRecord::Base,我得到一个NoMethodError,试图在其上调用define_method。任何想法?这可能很明显,但我对 Ruby on Rails 的细微之处还比较陌生。
  • define_method 仅在Module 上定义,但object 不是Module,而是Thing
猜你喜欢
  • 2012-08-19
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 2016-09-01
  • 2012-09-16
  • 2012-12-18
  • 2020-01-09
  • 1970-01-01
相关资源
最近更新 更多