猴子补丁中的代码应该放在哪里?

15

我看到的所有关于猴子补丁的内容都建议这样做:

class String
  def foo
    #your special code 
  end
end

但我找不到任何关于在哪里放置这段代码的指示。在Rails应用程序中,我可以把它放在任何我想放的地方吗?是在模块中?还是在模型中?

我需要在定义我的monkeypatch的文件中包含什么吗?我需要在想要使用它的每个地方都包含我的monkeypatch吗?


2
我建议您阅读有关Refinements的内容。它们旨在帮助避免我们在猴子补丁方面看到的问题。 - the Tin Man
1
在你开始这个过程之前,考虑创建一个String的子类来实现你想要的功能。只有当你需要普遍改变事物的行为时才需要这样做。 - tadman
3个回答

19

这方面没有固定的规则。从技术上讲,您可以在任何地方打开它(类;并添加您的方法)。我通常会创建一个特殊的文件,称为monkey_patches.rb,并将其放置在我的Rails应用程序的config/initializersmisc文件夹中,以便如果发生冲突,我知道该去哪里查找。

此外,我建议使用Module来包装猴子补丁。有关更多信息,请查看3种不制造混乱的猴子补丁方式

他的示例:

module CoreExtensions
  module DateTime
    module BusinessDays
      def weekday?
        !sunday? && !saturday?
      end
    end
  end
end

DateTime.include CoreExtensions::DateTime::BusinessDays

2
我尽量给 config/initializers 目录下的文件起一个有意义的名称,比如这个例子中的 business_days.rb,而不是像 monkey_patches.rb 或者 embarrassing_collection_of_unfortunate_hacks.rb 这样容易引起困惑的泛泛之名。如果你使用的编辑器支持通过名称快速打开文件,那么只要名称一致,你就可以很容易地打开并进行必要的修改。 - tadman

4
我使用了Justin Weiss在3种不制造混乱的猴子补丁方法中描述的以下技术。
当在纯Ruby或者一个gem中,你定义了一个模块并且在某个文件中引用它,然后将该模块include(或extend到所需的类中。
module StringMonkeypatch
  def foo
    #your special code 
  end
end

String.include StringMonkeypatch

当你在Rails中时,你可能想要定义模块在一个可以自动加载的位置(查找autoload_paths),并且按照Rails的命名规范进行定义。
例如,如果你要修改Sidekiq::Testing gem类,你应该按照文件结构进行镜像操作。
# in /app/<something telling>/sidekiq/testing/monkeypatch.rb
module Sidekiq::Testing::Monkeypatch
  def foo
    #your special code 
  end
end

# in /config/environment.rb, at the bootom
Sidekiq::Testing.include Sidekiq::Testing::Monkeypatch

1

我来发表一下意见,因为我花了很长时间才弄明白这个问题,因为很少有解决方案可行。

• 我不得不使用普通的require。我把它放在config/application.rb文件中。如果你把它放在app目录下像一些人建议的那样,文件对我来说并不会自动加载。我不知道为什么。

patching_file_path = File.expand_path("./lib", Dir.pwd) Dir[patching_file_path+'/*.rb'].each {|file| require file }

• 我还在我要求的文件中放了一个临时的puts "I'm Working!,这样我就可以检查控制台看它是否真正加载了。

• 此外,如果你正在使用spring loader,在启动控制台之前,你应该在终端中执行bin/spring stop。否则,它不会加载新文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接