【问题标题】:override lib module method for specific rails environment覆盖特定 rails 环境的 lib 模块方法
【发布时间】:2011-07-29 19:00:15
【问题描述】:

我有一个库模块,我想根据我正在运行的 rails 环境覆盖

模块位于 lib/package/my_module.rb:

module Package
  module MyModule
    puts "Defining original module"
    def foo
      puts "This is the original foo"
    end
  end
end

我已经能够使用Overriding a module method from a gem in Rails 处的信息部分解决 - 特别是在我的环境/dev_stub.rb 中:

Package::MyModule.module_eval do
 puts "Defining override"
 def foo
   puts "This is foo override"
 end
end

(当 rails 尝试查找与包相关的其他类时,该链接上的其他解决方案似乎会导致错误)

现在,这似乎可以让我大部分时间到达那里,并且如果我设置了就可以工作

config.cache_classes = true

...但是我想将其用作存根开发环境,并且对开发环境的此值的评论建议是使用 false... 在这种情况下,覆盖仅在第一次包含模块时才有效,以及任何后续时间,它都会使用原始版本。

我的问题:我这样做是否正确?我可以破解 lib 模块本身以根据 RAILS_ENV 有条件地覆盖,但我想让它比这更干净......

编辑

我的用例是从控制器函数中引用它。如果我有

class SomethingController < ApplicationController
  def show
    Package::MyModule.foo
  end
end

config.cache_classes=false(我最想要的,因为它是一个开发环境),并通过我的网络浏览器(http://localhost/something/show)访问该操作,然后我第一次点击它时,我的覆盖被加载并且它可以工作,但是第二次和任何后续时间,原始库类被重新加载(在我的控制台上输出“定义原始模块”而没有“定义覆盖”),并且覆盖丢失。

我尝试的另一种选择是将config.load_paths += %W( #{RAILS_ROOT}/lib_patch/#{RAILS_ENV}) 之类的内容添加到 environment.rb - 但是如果不在原始库中放入显式挂钩以基本上加载补丁(如果存在),则定义相同的模块/类并不能很好地工作

编辑 2(响应@apneadiving 的回答)

我尝试在没有 module_eval 的情况下执行此操作,并且仅在 development_stub.rb 中使用以下内容:

require 'package/my_module'
module Package
  module MyModule
    puts "Defining override"
    def foo
      puts "This is foo override"
    end
  end
end

我最初遇到的问题是 Rails 不再自动查找我的 lib 目录中的所有内容,我需要在所有其他 lib 文件(以及引用这些 lib 的控制器)中添加“require”语句以覆盖它们的所有依赖项。虽然这一切都完成了,但它确实有效,但它也具有与config.cache_classes=true 类似的效果,即所有库类都不会在更改时重新加载,即使在我没有猴子补丁的常规开发环境中也是如此(因为所有的 'require' 语句都被添加了)。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    在 dev_stub.rb 中设置 config.cache_classes=true 并使用 module_eval 来定义问题中描述的补丁似乎是实现目标的方法 - 为不支持的模块创建特定于环境的补丁影响代码路径和 Rails 类加载行为的其他环境。

    【讨论】:

      【解决方案2】:

      您可以简单地覆盖模块,它是不带module_eval 的实例。

      我猜你的模块是作为 Mixin 包含的,它的方法不受你的猴子补丁的影响。

      这就是alias_method_chain 发挥作用的地方。

      查看this great article,了解您应该如何使用它来满足您的需求。

      【讨论】:

      • 我实际上在不使用 module_eval 的情况下尝试过它,但是 Rails 中的某些东西不喜欢这样,当我尝试使用我的其他 lib 代码时,它会导致找不到定义。我将我的模块用作 Mixin,尽管我要覆盖的方法也在同一个模块中,所以我不确定 alias_method_chain 在这里是否有用。
      • 刚刚通过简单的重新定义重试了覆盖模块方法,它工作正常。我不能再帮你了。
      • 我运行的是旧版本的 Rails (2.3.8),所以可能与它有关?
      • 我不这么认为。无论 Rails 版本如何,这都是纯粹的红宝石。
      • 我已经编辑了我的问题,以提供有关 Rails 上下文的更多详细信息,以及为什么补丁只能在第一次工作。
      猜你喜欢
      • 2015-03-10
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 2013-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      相关资源
      最近更新 更多