Как расширить класс из инициализатора и перезагрузить его в среде разработки?

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

require 'qwerty/core/user'
User.send :include, Qwerty::Core::Extensions::User

Однако при разработке перед каждым запросом (и после перезагрузки! вызывается в консоли) все модели перезагружаются, но поскольку инициализаторы не запускаются снова, модуль не включается. Оставить модель с "отсутствующими частями".

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

На данный момент я просто добавил файл before_filter, который включает модуль, если в среде разработки. Но у меня есть копирование/вставка и дублирование кода в инициализаторе и контроллере приложений.

  # Class extensions in initalizers are over-writtern each request
  def development_loading
    if RAILS_ENV == 'development'      
      User.send :include, Qwerty::Core::Extensions::User
    end
  end

Есть ли лучший способ?

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

Ответ 1

environment.rb

config.to_prepare do
  User.send :include, Qwerty::Core::Extensions::User
end

Код - это блок, который запускается перед каждым запросом в режиме разработки и один раз в режиме производства.

Ответ 2

В Rails 3.x вы можете настроить блок для запуска при каждом перезагрузке (в режиме разработки или при config.cache_classes = false). Это означало бы инициализацию:

ActionDispatch::Callbacks.to_prepare do
    # configure stuff or initialize
end

Ответ 3

Чуть более элегантное решение, чем принятое, поскольку оно может быть вставлено в инициализатор:

require 'dispatcher'

Dispatcher.to_prepare do
  # stuff that needs to happen once per initialization
end

Ответ 4

Сначала я собирался посоветовать что-то о добавлении каталога "development" в начало вашего пути загрузки в режиме разработки, так что ваши ревизии всегда будут перезагружены сначала... Но потом мне пришло в голову, что вы сказали что-то запутанное.

Модель, которую вы пытаетесь расширить. Это в плагине? Плагины не должны перезагружаться по умолчанию в режиме разработки, если приложение явно не говорит, что они должны в своей конфигурации установить Config.reload_plugins? в false.

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

Dependencies.load_once_paths << lib_path

Подробнее см. в документах Rails в классе Configuration: http://api.rubyonrails.org/classes/Rails/Configuration.html#M002536

Ответ 5

Почему вы используете инициализаторы для включения функций?

Попробуйте вместо этого:

require 'qwerty/core/user'
class User < ActiveRecord::Base
  include Qwerty::Core::Extensions::User
  # bla bla
end