Redmine插件Issue销毁时无法访问IssueRelation的问题求助
Redmine插件开发:销毁Issue时无法访问IssueRelation的解决方案
问题原因分析
- Redmine关联删除策略限制:Redmine的
Issue模型与IssueRelation的关联使用dependent: :delete_all,该策略直接通过SQL批量删除关联记录,不会触发IssueRelation的任何回调(包括destroy方法)。同时删除操作会在Issue的before_destroy回调完成后立即执行,因此after_destroy中关联记录已被删除,查询结果为空。 - around回调未执行核心流程:你使用的
around_destroy回调方法未调用yield,导致Rails无法触发后续的销毁逻辑,进而出现异常的查询结果。 - ActiveRecord缓存影响:销毁流程中ActiveRecord可能优先读取对象缓存状态,而非实时查询数据库,导致关联记录查询为空。
解决方案
方案1:在before_destroy中提前加载关联记录
利用before_destroy执行时关联记录尚未被删除的时机,提前将所有关联关系加载到内存,再处理关联Issue的自定义字段:
module RedmineMyPlugin module Patches module IssuePatch extend ActiveSupport::Concern included do before_destroy :notify_related_issues, if: :is_tracker_diag? end def self.apply_patch Issue.send(:include, RedmineMyPlugin::Patches::IssuePatch) end module InstanceMethods def notify_related_issues # 提前加载所有关联的IssueRelation,避免后续被删除后无法获取 related_relations = IssueRelation.where("issue_from_id = ? OR issue_to_id = ?", self.id, self.id).to_a # 遍历关联Issue,修改自定义字段 related_relations.each do |relation| target_issue = relation.issue_from == self ? relation.issue_to : relation.issue_from # 替换为你的自定义字段ID和目标值 custom_field = target_issue.custom_fields.find_by(id: YOUR_CUSTOM_FIELD_ID) if custom_field target_issue.set_custom_field_value(custom_field, "更新后的值") target_issue.save!(validate: false) # 无需验证可加此参数 end end end end end end end
方案2:修复around_destroy回调(若仍需使用)
如果坚持使用around_destroy,必须在方法中调用yield触发销毁流程,同时提前加载关联记录:
module InstanceMethods def notify_related_issues # 销毁前:提前加载关联记录 related_relations = IssueRelation.where("issue_from_id = ? OR issue_to_id = ?", self.id, self.id).to_a yield # 执行销毁操作(包括删除关联记录) # 销毁后:使用提前加载的记录处理关联Issue related_relations.each do |relation| target_issue = relation.issue_from == self ? relation.issue_to : relation.issue_from # 自定义字段修改逻辑... target_issue.save! end end end
方案3:修改关联删除策略(不推荐)
若需要触发IssueRelation的destroy回调,可重写Issue的关联选项,将dependent: :delete_all改为dependent: :destroy,但此操作会降低销毁性能(逐个销毁关联记录而非批量SQL删除),且可能与Redmine原生逻辑冲突,需充分测试:
included do # 重写关联,替换dependent选项 has_many :relations, class_name: 'IssueRelation', foreign_key: 'issue_from_id', dependent: :destroy has_many :reverse_relations, class_name: 'IssueRelation', foreign_key: 'issue_to_id', dependent: :destroy end
关键注意事项
- 修改自定义字段时,建议使用Redmine标准方法
set_custom_field_value,避免直接操作custom_field_values引发异常。 - 修改关联删除策略可能在Issue关联大量关系时引发性能问题,需谨慎评估使用场景。
内容的提问来源于stack exchange,提问作者Ctrl Maj Sup
相关产品推荐
相关产品推荐

