【问题标题】:Where to put code when monkey patching猴子补丁时在哪里放置代码
【发布时间】:2017-06-02 00:05:02
【问题描述】:

我读到的关于猴子补丁的所有内容都说要做这样的事情:

class String
  def foo
    #your special code 
  end
end

但我找不到任何关于在何处放置此代码的说明。在 Rails 应用程序中,我可以把它放在我想要的任何疯狂的地方吗?在一个模块中?一个模型?

我是否需要在我定义我的猴子补丁的文件中包含一些内容?我是否需要在任何我想使用的地方都包含我的猴子补丁?

【问题讨论】:

  • 我建议您阅读有关Refinements 的信息。它们旨在帮助避免我们在猴子修补中看到的问题。
  • 在你走这条路之前,考虑创建一个String 的子类来满足你的需求。只有当您需要普遍改变事物的行为时,您才会想要这样做。

标签: ruby-on-rails ruby monkeypatching


【解决方案1】:

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

我还建议使用Module 来包装猴子补丁。查看3 ways to monkey patch without making a mess 了解更多信息。

他的例子:

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

DateTime.include CoreExtensions::DateTime::BusinessDays

【讨论】:

  • 我确实尝试将 config/initializers 中的文件命名为有意义的名称,例如在本例中为 business_days.rb,而不是像 monkey_patches.rbembarrassing_collection_of_unfortunate_hacks.rb 这样容易混淆的通用名称。如果您有一个允许按名称快速打开的编辑器,如果您必须在名称一致的情况下进行调整,则很容易将它们拉出来。
【解决方案2】:

我使用了 Justin Weiss 在3 Ways to Monkey-Patch Without Making a Mess 中描述的以下技术

例如,在 vanilla Ruby(一个 gem)中,您在某个您需要的文件中定义一个模块,然后 include (or 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

【讨论】:

    【解决方案3】:

    只是插话,因为我花了很长时间才弄清楚这一点,因为很少有解决方案奏效。

    • 我不得不使用普通的旧要求。我把它放在config/application.rb 文件中。如果您像某些人建议的那样将文件放在应用程序目录中,则该文件不会自动为我加载。我不知道为什么。

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

    • 我还在我试图要求的文件中放置了一个临时的puts "I'm Working!,以便我可以检查控制台以查看它是否实际加载。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 2012-09-16
      • 2012-12-18
      • 2020-01-09
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      相关资源
      最近更新 更多