首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修补Timecop的文件和CoreExtensions

如何修补Timecop的文件和CoreExtensions
EN

Stack Overflow用户
提问于 2019-07-26 19:10:04
回答 3查看 96关注 0票数 1

我需要猴子补丁文件。Timecop不影响文件系统报告的时间,这是File.atime使用的,而HttpClient在将文件发送到服务器时又使用这个时间,这又意味着VCR不完全按需要工作。AFAIK,这意味着我不能使用改进。

我不明白这是怎么回事

代码语言:javascript
复制
class File
  def atime
    "this one happens"
  end
end

module CoreExtensions
  module File
    module TimecopCompat
      def atime
        "this one does not"
      end
    end
  end
end

File.include CoreExtensions::File::TimecopCompat

File.new('somefile').atime # --> "this one happens"

为什么基于模块的猴子补丁不发生?我需要改变什么才能让它发挥作用?我应该用的是另一种猴子贴图吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-07-26 19:24:10

这个问题与include将模块附加到祖先链的方式有关。"Ruby模块:包括vs Prepend和扩展“非常详细地概述了includeprepend之间的差异。

看看这两个例子:

代码语言:javascript
复制
class Foo
  def hello
    "1"
  end
end

module Bar
  def hello
    "2"
  end
end

Foo.include Bar

Foo.new.hello
# => "1"
Foo.ancestors
# => [Foo, Bar, Object, Kernel, BasicObject]

对比

代码语言:javascript
复制
class Foo
  def hello
    "1"
  end
end

module Bar
  def hello
    "2"
  end
end

Foo.prepend Bar

Foo.new.hello
# => "2"
Foo.ancestors
# => [Bar, Foo, Object, Kernel, BasicObject]

基本上,您希望在您的情况下使用prepend,因为include不会覆盖现有的方法。

票数 3
EN

Stack Overflow用户

发布于 2019-07-26 19:50:40

include不是什么神奇的东西。实际上,它非常简单:它使模块成为它混入的类的超类。现在:超类方法是否覆盖子类方法?不,当然不是,情况正好相反。

因此,include不可能覆盖模块要进入的类的方法。

这就是prepend的作用所在,它在祖先层次结构开始时混合在一个模块中。(不幸的是,不能简单地用继承来解释,这是另一回事。)

票数 1
EN

Stack Overflow用户

发布于 2019-07-26 21:24:44

让我们在不改变问题的情况下简化您的示例。

代码语言:javascript
复制
module TimecopCompat
  def atime
    "this one does not"
  end
end

我没有使用类File,因为它已经有一个实例方法File#atime

代码语言:javascript
复制
File.new('temp').atime
  #=> 2019-07-16 20:20:51 -0700

正如其他答案所解释的,执行

代码语言:javascript
复制
File.include TimecopCompat

在以下方面的成果:

代码语言:javascript
复制
File.ancestors
  #=> [File, TimecopCompat, IO, File::Constants, Enumerable, Object, Kernel, BasicObject] 
File.new('temp').atime
  #=> 2019-07-16 20:20:51 -0700

而执行

代码语言:javascript
复制
File.prepend TimecopCompat

在以下方面的成果:

代码语言:javascript
复制
File.ancestors
  #=> [TimecopCompat, File, IO, File::Constants, Enumerable, Object, Kernel, BasicObject] 
File.new('temp').atime
  #=> "this one does not" 

然而,改变任何核心方法的行为是很糟糕的做法,因为它的原始行为可能依赖于程序的其他部分。

这里有两种可以接受的做法。第一种方法是创建一个方法(new_atime,例如),该方法的参数是File对象(file,例如):

代码语言:javascript
复制
file = File.new('temp')
x = new_atime(file)

new_atime不能以一个File对象作为它的接收方,但是为了一个安全和健壮的解决方案,这是一个很小的代价。

第二个选项是使用精练refine File类。

代码语言:javascript
复制
module RefinedFile
  refine File do
    def atime
      "this one does not"
    end
  end
end

class C
  using RefinedFile
  File.new('temp').atime
end
  #=> "this one does not"

我们可以确认File#atime没有在类C之外被更改。

代码语言:javascript
复制
File.new('temp').atime
  #=> 2019-07-16 20:20:51 -0700
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57225826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档