Ruby on Rails: изучение класса ActionController - вопрос по $ :. unshift activesupport_path и метод автозагрузки - PullRequest
2 голосов
/ 27 августа 2010

Внутри класса ActionController (rails / actionpack / lib / action_controller.lib) я обнаружил несколько странных кодов.У меня действительно нет наставника, чтобы изучать Ruby on Rails, поэтому этот форум - моя единственная надежда:

Вопрос № 1: Может ли кто-нибудь помочь мне объяснить эти строки кода?

begin
  require 'active_support'
rescue LoadError
  activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
  if File.directory?(activesupport_path)
    $:.unshift activesupport_path
    require 'active_support'
  end
end

Особенно строка с $ :. unshift activesupport_path

На мой взгляд, он пытается запросить класс active_support, и если это не сработает, он смотрит, является ли activesupport_path каталогом, если он есть, то.,,Я полностью потерял его.

Вопрос № 2: Для чего предназначен метод автозагрузки?

module ActionController
  # TODO: Review explicit to see if they will automatically be handled by
  # the initilizer if they are really needed.
  def self.load_all!
    [Base, CGIHandler, CgiRequest, Request, Response, Http::Headers, UrlRewriter, UrlWriter]
  end

  autoload :Base, 'action_controller/base'
  autoload :Benchmarking, 'action_controller/benchmarking'
  autoload :Caching, 'action_controller/caching'
  autoload :Cookies, 'action_controller/cookies'
  .
  .
  .

Вопрос № 3: Если я позже найду метод, я не понимаю, для чего, каклучший способ узнать?Что касается этого случая метода автозагрузки, я попытался найти его в своем проекте (у меня там заморожен код Rails), но не смог найти никакой подсказки.Я искал "автозагрузку по умолчанию".Я делаю что-то неправильно?Является ли моя IDE, TextMate просто не сократить его?

Спасибо!

1 Ответ

4 голосов
/ 27 августа 2010

Чтобы файл требовался, вы должны убедиться, что путь к нему указан в переменной Ruby $LOAD_PATH. Это сокращенная версия $: по устаревшим причинам, унаследованная от Perl.

Когда вы вызываете require, интерпретатор ищет файл .rb в каждом из указанных путей, пока не найдет совпадение. Если он найдет его, он загружен. Если нет, вы получите исключение.

Часто вы видите такие строки в файлах:

# script/something

# This appends "script/../lib" to the $LOAD_PATH, but this expands to
# something like "/home/user/project/lib" depending on the details of
# your installation.
$: << File.expand_path(File.join('..', 'lib'), File.dirname(__FILE__))

Вы можете использовать стандартные модификаторы Array для $LOAD_PATH, такие как unshift, push и <<.

Первый блок кода пытается загрузить active_support, и только в случае неудачи происходит модификация $LOAD_PATH для включения вероятного местоположения этого файла в зависимости от пути к файлу, выполняющему запрос require. Они делают это потому, что обычно все гемы из комплекта Rails устанавливаются в один и тот же базовый каталог.

Причина использования unshift состоит в том, чтобы поместить этот путь в самый высокий приоритет, вставленный в начало списка. Метод << или push добавляет к концу самый низкий приоритет.

Когда вы require файл загружаете, анализируете и анализируете, операция, которая может занять небольшое, но измеримое время и потребует больше памяти для хранения любых определений классов или методов внутри файла, а также как любые данные, такие как строковые константы, которые могут быть объявлены. Загрузка каждого элемента библиотеки, такого как ActiveRecord, с использованием require, потребует значительного объема памяти, и при этом будут импортированы все доступные драйверы базы данных, а не только те, которые фактически используются.

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

Вы часто будете видеть такие объявления:

class Foo
  # Declare the class Foo::Bar to be defined in foo/bar.rb
  autoload(:Bar, 'foo/bar')
end

При использовании autoload вам необходимо помнить, что имя класса всегда определяется в рамках модуля или класса, объявляющего его. В этом примере Bar находится в пределах Foo или Foo::Bar с использованием соглашений об именах Ruby.

Когда вы используете класс Bar, потребуется файл foo/bar.rb. Думайте об этом как о создании класса заглушки Bar, который превращается в реальный класс, как только он действительно выполняется.

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

Что касается третьего вопроса, доступная для поиска документация, такая как APIDock , поможет вам попытаться найти дополнительную информацию о методах. Различие между Ruby и Rails часто размыто, поэтому вам, возможно, придется проверить оба варианта, чтобы быть уверенным. Rails добавляет множество методов к основным классам Ruby, поэтому не принимайте список доступных методов для завершения с обеих сторон. Они работают вместе.

Иногда стоит искать def methodname, пытаясь выяснить, откуда происходит methodname, хотя это касается только обычных деклараций. Этот метод может быть псевдонимом из механизма, подобного method_alias, или он может быть динамически создан с использованием define_method, вы никогда не сможете быть уверены, пока не покопаетесь. По крайней мере, 90% методов в Rails объявлены обычным способом, поэтому в большинстве случаев простой поиск будет давать то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...