You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:38:12