是的,我知道我可以使用load
代替require
。但对我的用例来说,这不是一个好的解决方案:
当应用程序启动时,它requires
配置文件。每个环境都有自己的配置。配置设置常量。
应用启动时,只需要一个环境。但是,在测试期间,它会多次加载配置文件,以确保没有语法错误。
在测试环境中,可能会多次加载相同的配置文件。但我不想更改require
以加载,因为每次规范运行时,它都会重新加载配置。这应该通过require
来完成,因为如果配置已经加载,它会引发already initialized constant
警告。
我能看到的最干净的解决方案是在任何配置规范之后手动重置配置文件的require标志。
有没有办法在Ruby中做到这一点?
编辑:添加代码。
当应用程序启动时,它会调用init文件:
init.rb:
require "./config/environments/#{ ENV[ 'RACK_ENV' ]}.rb"
config/environments/test.rb:
APP_SETTING = :foo
config/environments/production.rb:
APP_SETTING = :bar
spec/models/config.rb: # It's not a model spec...
describe 'Config' do
specify do
load './config/environments/test.rb'
end
specify do
load './config/environments/production.rb'
end
答案 0 :(得分:2)
是的,可以做到。您必须知道要重新加载的文件的路径。有一个特殊变量$LOADED_FEATURES
,用于存储已加载的内容,并由require
用于决定是否在再次请求时加载文件。
这里我假设您要重新申请的文件名称中都有唯一的路径/myapp/config/
。但希望您可以看到这适用于您可以编码的路径名称的任何规则。
$LOADED_FEATURES.reject! { |path| path =~ /\/myapp\/config\// }
就是这样。 。 。
一些警告:
require
不存储或遵循任何类型的依赖树,以了解它应该"应该"装了。因此,您需要确保从您在规范中运行的require
命令开始的require
完整链,以重新加载配置,并包括您需要加载的所有内容,路径。
这不会卸载类定义或常量,只是重新加载文件。事实上,这实际上是require
所做的,它只是在内部调用load
。因此,所有关于重新定义常量的警告消息也需要通过取消定义您希望在文件中定义的常量来处理。
您的配置和规格可能设计无需执行此操作。
答案 1 :(得分:1)
如果你真的想这样做,这是一种不会泄漏到你的测试过程中的方法。为您要测试的每个配置文件分叉一个进程,通过IO.pipe
将状态传回测试进程,并根据结果失败/继续测试。
你可以随心所欲地使用你发送给管道的东西......
这是一个快速而又肮脏的例子,向您展示我的意思。
配置
# foo.rb
FOO = "from foo"
另一个配置
# bar.rb
FOO = "from bar"
一些错误的配置
# witherror.rb
asdf
和你的"测试"
# yourtest.rb
def load_config(writer, config_file)
fork do
begin
require_relative config_file
writer.write "success: #{FOO}\n"
rescue
writer.write "fail: #{$!.message}\n"
end
writer.close
exit # maybe this is even enough to NOT make it run your other tests...
end
end
rd, writer = IO.pipe
load_config(writer, "foo.rb")
load_config(writer, "bar.rb")
load_config(writer, "witherror.rb")
writer.close
puts rd.read
puts rd.read
puts rd.read
puts FOO
输出结果为:
success: from foo
success: from bar
fail: undefined local variable or method `asdf' for main:Object
yourtest.rb:24:in `<main>': uninitialized constant FOO (NameError)
如您所见,FOO常数不会泄漏到您的测试过程等。 当然,你只有一半的时间,因为还有更多的东西,确保只有一个进程运行测试等。
坦率地说,我不认为这是一个好主意,无论你选择何种方法,因为你会打开一堆蠕虫,而且那里没有真正干净的方法。