Redmine 插件 - 检测模块的启用和禁用
我正在使用一个外部框架 (redmine),该框架有一个 Project
模型,该模型 has_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
可以用于检测删除,但事实并非如此。 发生这种情况是因为对 Project.enabled_module_names=
的 enabled_modules.clear
调用不会调用模块上的“destroy”。它只是将它们的 project_id
设置为 nil。所以我想我应该使用 after_update
或 before_update
。
如果我使用 after_update
,如何获取“上一个”project_id
?
如果我使用 before_update
,如何区分“刚刚更新”的模块和 project_id 将重置为 nil 的模块?
我应该在这里使用完全不同的方法吗?
编辑:我只是发现我可以通过“_was”获取旧值(即self.project_was
)。但是,collection.clear
似乎没有触发更新回调。还有其他解决方案吗?
编辑2:更改标题
I'm working with an external framework (redmine) which has one Project
model that has_many EnabledModules
.
Projects can have EnabledModules "attached" or "removed" via the module names, like this:
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
I'd like to detect when new modules are attached/removed via callbacks on EnabledModule
, and not modify the "original source code" if possible.
I can detect "attachments" like this:
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
I thought that a before_destroy
would work for detecting removals, but it will not.
This happens because the enabled_modules.clear
call on Project.enabled_module_names=
, doesn't invoke 'destroy' on the modules. It just sets their project_id
to nil. So I figured I should use a after_update
or before_update
.
If I use after_update
, how can I get the 'previous' project_id
?
If I use before_update
, how can I differentiate between modules that are 'just updated' and modules whose project_id is going to be reset to nil?
Should I use a totally different approach here?
EDIT: I just found out that I could get the old values with '_was' (i.e. self.project_was
). However, collection.clear
doesn't seem to trigger update callbacks. Any other solutions?
EDIT 2: Changed title
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看来 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),因此您可能至少需要选择该版本。
It looks like revision 2473 onwards of Redmine should solve your problem. See the diffs here:
http://www.redmine.org/projects/redmine/repository/diff/trunk/app/models/project.rb?rev=2473&rev_to=2319
Basically the code has been modified such that removed modules are destroyed rather than deleted, the difference being that model callbacks are not fired for deletes.
There's another related fix in revision 3036 that seems important (see http://www.redmine.org/issues/4200) so you might want to pick up at least that version.
我最终重新实现了项目的
enabled_module_names=
方法,包括vendor/plugins/my_plugin/lib/my_plugin/patches/project_patch.rb 和别名中的文件。我还必须在我的供应商/插件/my_plugin/init.rb 文件中包含一些代码:
此后,我能够在我的修补程序上检测到启用模块上的删除(通过
before_delete
)。I ended up reimplementing the
enabled_module_names=
method of projects, including a file in vendor/plugins/my_plugin/lib/my_plugin/patches/project_patch.rb and alias.I had to include some code on my vendor/plugins/my_plugin/init.rb file, too:
After this, I was able to detect deletions on enabled modules (via
before_delete
) on my patcher.关于:
也许可以尝试project_id_was,它由 ActiveRecord::脏
Regarding:
Maybe try project_id_was, it's provided by ActiveRecord::Dirty