是否有一个版本的requireruby可以加载整个文件,或者什么也没有?
问题是需要从顶部开始加载,如果它遇到问题,你最终得到未完成的定义,例如,class A即使module C未定义,以下仍然会加载:
class B
include C
end
Run Code Online (Sandbox Code Playgroud)
在我的特定情况下,我有一大堆相互依赖的文件,以及一个加载这些文件的加载器.举例来说,我将文件集简化为4个文件(a.rb,b.rb,c.rb和w.rb).以下是这些文件的列表:
# In file a.rb
class A
@foo = []
@foo.push("in A")
def self.inherited(subclass)
foo = @foo.dup
subclass.instance_eval do
@foo = foo
end
end
def self.get_foo
@foo
end
end
# In file b.rb
class B < A
include C # if C is not already defined, the following line will not get executed although B will be defined.
@foo.push("in B")
end
# In file c.rb
module C
end
# In file w.rb
class W < B
@foo.push("in W")
end
Run Code Online (Sandbox Code Playgroud)
加载器通过获取当前文件列表来工作,试图逐个地要求它们.如果任何文件失败,它将保留在列表中,稍后再次尝试.代码是这样的:(为简单起见删除了很多细节)
# In file loader.rb
files = Dir["*.rb"].reject { |f| f =~ /loader/ }
files.sort! # just for the purpose of the example, to make them load in an order that causes the problem
files.reject! { |f| require(f) rescue nil } while files.size > 0
Run Code Online (Sandbox Code Playgroud)
我最终想要它加载A,然后发现B不能单独加载(所以跳过它),然后加载C,然后找到W还不能加载(所以跳过它),然后回到B然后W .
在那种情况下,输出p W.get_foo将是["in A", "in B", "in W"],这是我想要的.
实际发生的是它加载A,然后部分加载B,然后是C,然后当它到达W时,它认为它可以加载它(因为B已经定义).这会self.inherited在不正确的时间触发代码,并复制非就绪值@foo,从而导致输出p W.get_foo错误["in A", "in W"].
拥有全有或全无的require解决方案.
有任何想法吗?
如果一个文件依赖于另一个文件,那么该文件应该需要依赖项本身.例如,b.rb应该看起来像这样:
require 'a'
require 'c'
class B < A
include C # if C is not already defined, the following line will not get executed although B will be defined.
@foo.push("in B")
end
Run Code Online (Sandbox Code Playgroud)
并且w.rb应该如下所示:
require 'b'
class W < B
@foo.push("in W")
end
Run Code Online (Sandbox Code Playgroud)
之后,外部装载顺序不再重要,"全有或全无"需要接近.当b加载时,它将首先看到需要a并意识到它已经被加载,然后它将需要,c因为它意识到它还没有加载它.当再次需要c时,它将从外循环中跳过它.
注意:注意你的$ LOAD_PATH和传递给的路径require.Ruby只在路径相同时才识别重复需求.最好使用相对路径(相对于$ LOAD_PATH中的路径)而不是绝对路径; 否则,文件可能会加载两次.