Существует ли версия require
в ruby, которая либо загружает весь файл, либо вообще ничего?
Проблема заключается в том, что require начинает загрузку сверху, и, если возникают проблемы, вы, например, получаете незавершенные определения, следующее все равно будет загружать class A
, даже если module C
не определено:
class B
include C
end
В моем конкретном случае у меня есть большой набор взаимозависимых файлов и загрузчик, который загружает эти файлы. В качестве примера я приведу просто набор файлов из 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
Загрузчик работает, получая список текущих файлов, пытаясь запросить их один за другим. Если какой-либо файл завершается ошибкой, он остается в списке и повторяется позже Код выглядит примерно так: (удалено много деталей для простоты)
# 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
В конечном счете, я бы хотел, чтобы он загрузил 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
решит это.
Есть идеи?