代码之家  ›  专栏  ›  技术社区  ›  kikito

Redmine插件-检测模块的启用和禁用

  •  0
  • kikito  · 技术社区  · 15 年前

    我正在使用一个外部框架(Redmine),它有一个 Project 有很多的型号 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 .

    如果我使用 后更新 ,如何获取“上一个” 项目编号 ?

    如果我使用 更新前 ,如何区分“刚刚更新”的模块和项目ID将重置为零的模块?

    我应该在这里使用完全不同的方法吗?

    编辑:我只是 found out 我可以用“曾经”得到旧的价值观。 self.project_was )然而, collection.clear 似乎不会触发更新回调。还有其他的解决办法吗?

    编辑2:更改标题

    3 回复  |  直到 15 年前
        1
  •  1
  •   nioq    15 年前

    看来,修订版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 )所以你可能至少想要那个版本。

        2
  •  1
  •   kikito    15 年前

    我最终重新实现了 enabled_module_names= 项目方法,包括vendor/plugins/my_plugin/lib/my_plugin/patches/project_patch.rb和alias中的文件。

    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
    

    我还必须在供应商/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 )在我的补丁上。

        3
  •  0
  •   Kamil Sarna    15 年前

    关于:

    如果我在更新后使用,如何获取“上一个”项目ID

    可能是Try项目,它是由 ActiveRecord::Dirty