我正在使用一个外部框架(redmine),它有一个Project
模型,其中包含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
的{{1}}调用不会在模块上调用'destroy'。它只是将Project.enabled_module_names=
设置为零。所以我想我应该使用project_id
或after_update
。
如果我使用before_update
,我怎样才能获得'上一个'after_update
?
如果我使用project_id
,我如何区分“刚更新”的模块和project_id将重置为nil的模块?
我应该在这里使用完全不同的方法吗?
编辑:我只是found out我可以使用'_was'(即before_update
)获取旧值。但是,self.project_was
似乎没有触发更新回调。还有其他解决方案吗?
编辑2:更改了标题
答案 0 :(得分:1)
看起来Redmine的2473版本应该可以解决您的问题。在这里看到差异: 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 :(得分:1)
我最终重新实现了项目的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
)。
答案 2 :(得分:0)