Почему автозагрузка, load_all! и требуют все используемые в active_support.rb? - PullRequest
10 голосов
/ 18 июня 2009

Я смотрел на active_support.rb, чтобы попытаться понять процесс загрузки, который он использует. Он использует три метода загрузки: load_all!, autoload и require. Зачем использовать три разных способа загрузки в один и тот же файл?

module ActiveSupport
  def self.load_all!
    [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom, TimeWithZone]
  end

  autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
  autoload :Base64, 'active_support/base64'
  autoload :BasicObject, 'active_support/basic_object'
  autoload :BufferedLogger, 'active_support/buffered_logger'
  autoload :Cache, 'active_support/cache'
  autoload :Callbacks, 'active_support/callbacks'
  autoload :Deprecation, 'active_support/deprecation'
  autoload :Duration, 'active_support/duration'
  autoload :Gzip, 'active_support/gzip'
  autoload :Inflector, 'active_support/inflector'
  autoload :Memoizable, 'active_support/memoizable'
  autoload :MessageEncryptor, 'active_support/message_encryptor'
  autoload :MessageVerifier, 'active_support/message_verifier'
  autoload :Multibyte, 'active_support/multibyte'
  autoload :OptionMerger, 'active_support/option_merger'
  autoload :OrderedHash, 'active_support/ordered_hash'
  autoload :OrderedOptions, 'active_support/ordered_options'
  autoload :Rescuable, 'active_support/rescuable'
  autoload :SecureRandom, 'active_support/secure_random'
  autoload :StringInquirer, 'active_support/string_inquirer'
  autoload :TimeWithZone, 'active_support/time_with_zone'
  autoload :TimeZone, 'active_support/values/time_zone'
  autoload :XmlMini, 'active_support/xml_mini'
end

require 'active_support/vendor'
require 'active_support/core_ext'
require 'active_support/dependencies'
require 'active_support/json'

I18n.load_path << "#{File.dirname(__FILE__)}/active_support/locale/en.yml"

Ответы [ 2 ]

16 голосов
/ 18 июня 2009

Я не знаю точно, почему Rails использует три разных метода загрузки (на самом деле два - см. Ниже). Но я вообще знаю, почему кто-то может.

Require означает «загрузить это прямо сейчас». autoload означает «загрузить это, когда вам нужно его использовать». Обычная причина использования обоих заключается в том, что у вас есть некоторые файлы, которые, как вы предполагаете, будут использоваться при каждом вызове программы; и другие, которые не являются обязательными. Например, в приложении Rails, которое не использует устаревшие методы, вам никогда не понадобится Deprecation; так зачем замедлять начальную настройку, загружая этот файл?

В других случаях вы можете различать файлы, которые понадобятся на раннем этапе выполнения программы, и файлы, которые могут ждать. Например, вам вряд ли понадобится Gzip до тех пор, пока не поступит первый запрос. Таким образом, с помощью автозагрузки вы можете на некоторое время отключить начальную настройку за счет небольшого замедления для первого запроса.

Вы можете спросить, ну почему бы просто не использовать autoload для всего? Зачем загружать что-нибудь , прежде чем это будет абсолютно необходимо? Одна из причин заключается в том, что автозагрузка работает только для констант. Так, например, active_support/core_ext добавляет кучу методов в Numeric, чтобы вы могли написать код, такой как 3.days, 6.minutes и 16.seconds.ago. В 3.days нет константы, поэтому вы не можете запустить автозагрузку для этого выражения. (И вы не можете автоматически загрузить Numeric, потому что базовый класс уже загружен - это просто расширения, которые вы хотите добавить.)

Наконец, этот класс на самом деле не использует три метода загрузки; он использует два, и предоставляет один (своего рода). load_all! используется Rails::Initializer до

# Preload all frameworks specified by the Configuration#frameworks.
# Used by Passenger to ensure everything's loaded before forking and
# to avoid autoload race conditions in JRuby.

Я не знаю деталей, и я не знаю, почему эти конкретные модули предварительно загружены (а не остальные). Но так как это предназначено для поддержки определенных сред, вы можете понять, почему может потребоваться код, отдельный от механизма загрузки по умолчанию.

1 голос
/ 18 июня 2009

Метод autoload ruby ​​может использоваться для связи константы с именем файла, которое будет загружено при первой ссылке на указанную константу. Это избавляет вас от необходимости загружать всю инфраструктуру при запуске.

Похоже, что метод load_all! вызывается из направляющих initializer.rb и используется для предварительной загрузки всех платформ, которые настроены для предварительной загрузки. Это работает, вызывая каждый фреймворк load_all! метод, который просто ссылается на массив констант ... который запускает автозагрузку.

Согласно комментариям в initializer.rb для preload_frameworks ...

# Preload all frameworks specified by the Configuration#frameworks.
# Used by Passenger to ensure everything's loaded before forking and
# to avoid autoload race conditions in JRuby.

require - загрузка основных файлов, необходимых для конкретной платформы.

...