Когда вызывать «требуют» в Rails? - PullRequest
24 голосов
/ 27 августа 2010

У меня есть более концептуальный вопрос в Rails ... или Ruby по этому вопросу:

Лучше ли вызывать require прямо перед тем методом, который нуждается в нем, группировать my require в начале класса или где-нибудь в инициализаторе при загрузке Rails?

Имеет ли это значение с точки зрения производительности? С точки зрения читабельности? Имеет ли значение, если я использую Rails 3?

Спасибо!

Ответы [ 2 ]

20 голосов
/ 28 августа 2010

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

if (user.using_openid?)
  require 'openid'

  # ... Do OpenID stuff
end

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

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

require 'library1'
require 'library2'
require 'library3'
require 'library4'
require 'library5'

# Other libraries loaded as required:
#  * slowimagelibrary
#  * slowencryptionlibrary
#  * openid

Возможно, это не проблема с bundler , потому что вы можете объявить свои гемы более формально, а фактический вызов require может произойти позже.

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

Если вы рассматриваете ванильный Ruby, 'require' в основном используется в первых строках, потому что тогда вы уверены, что у вас есть доступ к тому, что вам нужно, и вам легче найти и прочитать то, что вам нужно.

Есть несколько случаев, когда вы хотите загрузить гем только в методе, потому что это на самом деле не нужно для работы вашего скрипта (например: дополнительная визуализация).

Я думаю, что с Rails это зависит от того, что вы хотите сделать.

Если вы используете Bundler, вы можете предположить, что ваш драгоценный камень «необходим» (вы, конечно, можете переопределить то, что требуется, с помощью опции: require).

Если вы хотите выполнить автозагрузку при запуске сервера (например, валидаторы или компоновщики форм), вам следует посмотреть, как это сделать с помощью config (autoload_paths и eager_load_paths).

require может также использоваться для загрузки только части драгоценного камня, например, расширения к нему. Тогда, конечно, требуется, где конфигурация.

Вас может беспокоить, если вы работаете в многопоточной среде, поскольку у них есть некоторые проблемы с этим. Затем вы должны убедиться, что все загружено, прежде чем запускать ваши потоки. (Что-то вроде константы класса загружено, но методов еще нет, была хорошая статья, но я больше не могу ее найти).

Возможно, вы также захотите попробовать {Module, Kernel} .autoload, Rails широко использует его для загрузки только того, что необходимо при доступе (но это выглядит довольно некрасиво).

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

def Object.const_missing c
  if (file = Dir["#{c.downcase}.rb"]).size == 1 
    require_relative(file)
  end
  if const_defined? c
    const_get c
  else
    super # Object < Module
  end
end

Что касается производительности, то запрос на запрос является относительно дорогим, поэтому, если вы знаете, что собираетесь его использовать, делайте это только один раз, если это возможно. Однако для управления сложными зависимостями в вашем проекте вам могут потребоваться относительные файлы. Тогда require_relative - это путь в 1.9.

Наконец, для проекта я бы порекомендовал требовать все в главном файле в lib / с некоторым выражением Dir["**/*.rb"]. Тогда вам редко понадобится require_relative, потому что это необходимо, только если вы ссылаетесь в теле класса на другую константу (все содержимое методов не разрешено, поэтому с этим проблем нет).

Другим решением было бы определить эти константы в вашем основном файле, это также дало бы вам представление о структуре.

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