Подтвердить что ты не робот

Когда вызывать "требовать" в Rails?

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

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

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

Спасибо!

4b9b3361

Ответ 1

Если вы беспокоитесь о производительности, вам следует требовать вещи в контексте того, где они нужны, чтобы, если эта часть вашего кода не используется, библиотека не загружается. Любые последующие вызовы 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 вызов может прийти позже.

Ответ 2

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

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

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

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

Если вы хотите выполнить автозагрузку при запуске сервера (например, валидаторы или сборщики форм), вы должны посмотреть, как это сделать с конфигурацией (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, потому что это необходимо только в том случае, если вы ссылаетесь в теле класса на другую константу (все содержимое методов не разрешено, поэтому нет проблем с этим).

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