【发布时间】: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