Каким образом требуются перезагрузка require, require_dependency и констант в Rails? - PullRequest
63 голосов
/ 22 сентября 2009

Чем require и require_dependency отличаются?
Как require_dependency может автоматически перезагружать классы в разработке, но require не может?

Я копался в Rails 'ActiveSupport::Dependencies и коде dispatcher.rb. Что я видел в коде require_dependency, так это то, что он в основном добавляет константы в массив autoloaded_constants. Но он очищается в clear_application внутри диспетчера после каждого запроса.

Может ли кто-то дать четкое объяснение или указать мне на некоторые ресурсы, которые помогут?

Ответы [ 2 ]

119 голосов
/ 07 марта 2011

require (и его двоюродный брат load) являются основными методами Ruby. require_dependency - это метод, который помогает Rails справиться с проблемой управления зависимостями. Короче говоря, он позволяет Rails перезагружать классы в режиме разработки, чтобы вам не приходилось перезагружать сервер при каждом изменении кода. Платформа Rails require_dependency сделает ваш код, чтобы он мог отслеживать и перезагружать его после внесения изменений. Стандартный Ruby require этого не делает. Как разработчику приложения (или плагина / движка) вам не нужно беспокоиться о require_dependency, так как это чисто внутреннее отношение к Rails.

Волшебство процесса загрузки класса Rails заключается в модуле ActiveSupport :: Dependencies. Этот код расширяет стандартное поведение Ruby, позволяя коду внутри вашего приложения Rails автоматически загружать модули (включая классы, которые наследуются от Module) с использованием соглашений Rails о пути и именовании файлов. Это избавляет программиста от необходимости засорять свой код вызовами require, как в обычном Ruby-приложении.

Другими словами, это позволяет вам определить class Admin::User внутри файла app/models/admin/user.rb и дать Rails знать, о чем вы говорите, когда вы вызываете Admin::User.new из другой части приложения, такой как контроллер. Без ActiveSupport :: Зависимости вам придется вручную require все, что вам нужно.

Если вы используете статически типизированный язык, такой как C #, Java и т. Д., Это может быть сюрпризом: код Rails не загружается до тех пор, пока он не понадобится. Например, класс модели User не определен и user.rb не загружается, пока ПОСЛЕ того, как вы попытаетесь вызвать User.whatever_method_here. Rails не дает Ruby пожаловаться на эту отсутствующую константу, загружает код для User, а затем позволяет Ruby продолжать работу в обычном режиме.

Хотя я не могу говорить о ваших конкретных потребностях, я был бы очень удивлен, если бы вам действительно нужно было использовать метод require_dependency из плагина или движка. Если вы следуете соглашениям Rails, вам также не нужно настраивать $ LOAD_PATH вручную. Это не «путь рельсов».

В мире Ruby, а также в Rails простота и ясность являются ключевыми. Если все, что вы хотите сделать, - это написать плагин или движок, и вы уже углубляетесь во внутренности, тогда вы можете рассмотреть подход к своей проблеме под другим углом. Моя интуиция говорит мне, что вы, возможно, пытаетесь сделать что-то слишком сложное. Но опять же, я понятия не имею, что вы делаете точно !! :)

19 голосов
/ 14 ноября 2013

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

# app/controllers/my_engine/documents_controller.rb
require_dependency MyEngine::Engine.root.join('app', 'controllers', 'my_engine', 'documents_controller').to_s

module MyEngine
  class DocumentsController
    def show
      render :text => 'different'
    end
  end
end
...