2010-08-27 3 views
22

У меня есть более концептуальный вопрос в Rails ... или Ruby, если на то пошло:Когда нужно позвонить в Rails?

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

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

Спасибо!

ответ

19

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

Спасибо тадман, это соответствует тому, о чем я думал. Вывод: читаемость важнее производительности, за исключением случаев, когда требуется использование тяжелых. – Cimm

4

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

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

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

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

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

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

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

Возможно, вы также захотите попробовать {Module, Kernel}.Автозагрузка, 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, потому что это необходимо, только если вы ссылаетесь в теле класса на другую константу (все содержимое методов не разрешено, поэтому с этим нет никаких проблем).

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

Смежные вопросы