Обычным примером является использование Dispatcher.to_prepare
внутри init.rb
вашего плагина. Это необходимо, потому что в режиме разработки (или, как правило, если config.cache_classes = false
) Rails перезагружает все классы непосредственно перед каждым запросом для получения изменений без необходимости каждый раз полностью перезагружать сервер приложений.
Это, однако, означает, что вы должны применить свой патч снова после перезагрузки класса, так как Rails не может знать, какие модули были внедрены позже. Используя Dispatcher.to_prepare
, вы можете достичь именно этого. Код, определенный в блоке, выполняется один раз в производственном режиме и перед каждым запросом в режиме разработки, что делает его главным местом для базовых классов обезьяньего патча.
Преимуществом этого подхода является то, что вы можете иметь свои плагины автономными и не нужно ничего менять в окружающем приложении.
Поместите это в свой init.rb
, например. vendor/plugins/my_plugin/init.rb
require 'redmine'
# Patches to the Redmine core.
require 'dispatcher'
Dispatcher.to_prepare do
ApplicationController.send(:include, MyPlugin::ApplicationControllerPatch) unless ApplicationController.include?(RedmineSpentTimeColumn::Patches::IssuePatch)
end
Redmine::Plugin.register :my_plugin do
name 'My Plugin'
[...]
end
Ваш патч должен всегда находиться в пространстве имен внутри модуля, названного в честь вашего плагина, чтобы не было проблем с несколькими плагинами, определяющими одинаковые имена модулей. Затем поместите патч в lib/my_plugin/application_controller_patch.rb
. Таким образом, он будет автоматически загружен Rails Autoloader.
Поместите это в vendor/plugins/my_plugin/lib/my_plugin/application_controller_patch.rb
module MyPlugin
module ApplicationControllerPatch
def self.included(base) # :nodoc:
base.class_eval do
rescue_from AnException, :with => :rescue_method
def rescue_method(exception)
[...]
end
end
end
end
end