Redmine Plugins - Обнаружение включения и выключения модулей - PullRequest
0 голосов
/ 20 января 2010

Я работаю с внешней структурой (redmine), которая имеет одну Project модель, которая имеет_many EnabledModules.

Проекты могут иметь EnabledModules, «прикрепленные» или «удаленные» через имена модулей, например:

class Project < ActiveRecord::Base
  ...
  has_many :enabled_modules, :dependent => :delete_all
  ...
  def enabled_module_names=(module_names)
    enabled_modules.clear
    module_names = [] unless module_names && module_names.is_a?(Array)
    module_names.each do |name|
      enabled_modules << EnabledModule.new(:name => name.to_s)
    end
  end
end

Я хотел бы определить, когда новые модули подключаются / удаляются с помощью обратных вызовов на EnabledModule, и не изменять «исходный код», если это возможно.

Я могу обнаружить «вложения», например:

class EnabledModule < ActiveRecord::Base
  belongs_to :project

  after_create :module_created

  def module_created
    logger.log("Module attached to project #{self.project_id}")
  end
end

Я думал, что before_destroy будет работать для обнаружения удалений, но не будет. Это происходит потому, что вызов enabled_modules.clear для Project.enabled_module_names= не вызывает 'destroy' для модулей. Он просто устанавливает их project_id на ноль. Поэтому я решил, что должен использовать after_update или before_update.

Если я использую after_update, как я могу получить «предыдущий» project_id?

Если я использую before_update, как я могу провести различие между модулями, которые «только что обновлены», и модулями, чей project_id будет сброшен на ноль?

Должен ли я использовать здесь совершенно другой подход?

РЕДАКТИРОВАТЬ: Я просто обнаружил , что я могу получить старые значения с помощью '_was' (т.е. self.project_was). Однако, collection.clear, похоже, не запускает обратные вызовы обновления. Любые другие решения?

РЕДАКТИРОВАТЬ 2: Изменение названия

Ответы [ 3 ]

1 голос
/ 22 января 2010

Похоже, что ревизия 2473 года в Redmine должна решить вашу проблему. Смотрите различия здесь: http://www.redmine.org/projects/redmine/repository/diff/trunk/app/models/project.rb?rev=2473&rev_to=2319

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

В ревизии 3036 есть еще одно исправление, которое кажется важным (см. http://www.redmine.org/issues/4200), так что вы можете выбрать хотя бы эту версию.

1 голос
/ 22 января 2010

В итоге я переопределил метод проектов enabled_module_names=, включая файл в vendor / plugins / my_plugin / lib / my_plugin / patches / project_patch.rb и псевдоним.

module MyPlugin
  module Patches
    module ProjectPatch
      def self.included(base)
        base.send(:include, InstanceMethods)
        base.extend(ClassMethods)
        base.class_eval do
          unloadable # Send unloadable so it will not be unloaded in development

          # This replaces the existing version of enabled_module_names with a new one
          # It is needed because we need the "destroy" callbacks to be fired,
          # and only on the erased modules (not all of them - the default 
          # implementation starts by wiping them out in v0.8'ish)
          alias_method :enabled_module_names=, :sympa_enabled_module_names=
        end
      end

      module ClassMethods
      end

      module InstanceMethods

        # Redefine enabled_module_names so it invokes 
        # mod.destroy on disconnected modules
        def sympa_enabled_module_names=(module_names)

          module_names = [] unless module_names and module_names.is_a?(Array)
          module_names = module_names.collect(&:to_s)
          # remove disabled modules
          enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)}

          # detect the modules that are new, and create those only
          module_names.reject {|name| module_enabled?(name)}.each {|name| enabled_modules << EnabledModule.new(:name => name) }
        end
      end
    end
  end
end

Мне также пришлось включить код в файл vendor / plugins / my_plugin / init.rb:

require 'redmine'

require 'dispatcher'

# you can add additional lines here for patching users, memberships, etc...
Dispatcher.to_prepare :redmine_sympa do
  require_dependency 'project'
  require_dependency 'enabled_module'

  Project.send(:include, RedmineSympa::Patches::ProjectPatch)
  EnabledModule.send(:include, RedmineSympa::Patches::EnabledModulePatch)

end

Redmine::Plugin.register :redmine_sympa do
# ... usual redmine plugin init stuff
end

После этого я смог обнаружить удаления на включенных модулях (через before_delete) на моем патчере.

0 голосов
/ 20 января 2010

Относительно:

Если я использую after_update, как я могу получить 'предыдущий' project_id

Может быть, попробовать project_id_was, он предоставляется ActiveRecord :: Dirty

...