【问题标题】:How to trigger a function when a custom field is edited/created in redmine在 redmine 中编辑/创建自定义字段时如何触发功能
【发布时间】:2020-04-07 07:26:59
【问题描述】:

我已经研究这个术语很多小时了,但我发现了一些有用的东西。 希望您能帮助我们构建这个 redmine 插件,或者提供一些研究链接来帮助我们找到正确的密钥。

我们想要构建什么

问题是我们想在 redmine 中更新一个自定义字段(我们将其命名为“Target_CF”),每当创建或更新另一个自定义字段时。 我们正在寻找增加 Target_CF 的可能值,因此我们可以选择所有自定义字段的名称。 当然,我们希望在不直接编辑 Redmine 的 Core 的情况下实现这一点,因此我们认为开发插件是最好的方法。

我们的插件还创建和配置了一个新的自定义字段(上面提到的那个),但我不会考虑这个,因为我认为它与此无关。

我们现在的位置

我们已经确定了一些可能对我们有用的钩子,如下所示:

  • :controller_custom_fields_new_after_save
  • :controller_custom_fields_edit_after_save

到目前为止,我们有以下目录/文件结构:

plugins/
  custom_plugin/
    init.rb
    lib/
      hooks.rb

我们写的代码

init.rb

require_dependency 'hooks'
Redmine::Plugin.register :custom_plugin do
  name 'custom_plugin'
  author 'author name'
  description 'description text'
  version '1.0.0'
end

hooks.rb

class Hooks < Redmine::Hook::ViewListener
  def controller_custom_fields_edit_after_save(context={ })
    @target_custom_field_name = "Target_CF"
    CustomField.find_by_name(@target_custom_field_name).possible_values.push(context[:custom_field].name)
  end
end

这段代码的结果是无。我的意思是,没有错误,没有更新,什么都没有。编辑/创建另一个自定义字段后,我们的可能值没有变化。我们确信有一些我们不知道的东西,一些概念或工作流程,因此我们做得很糟糕。 请帮助我们了解我们缺少什么。

之前我们已经成功开发了另一个覆盖某些视图的插件。所以我们在视图相关的插件方面有一点技能,但在控制器方面却是零经验。

我们正在使用 Bitnami 的 Redmine 3.2.0 堆栈和一个 mysql 数据库。

【问题讨论】:

    标签: plugins controller hook redmine custom-fields


    【解决方案1】:

    好吧,最后我们找到了如何扩展基本控制器的方法。我会把它贴在这里,希望这对那些发现我们有同样疑问的人有用。 经过更多研究,我们得出结论,必须扩展基本控制器,以免直接修改核心方法。

    这是我们最终的目录/文件结构:

    plugins/
      custom_plugin/
        init.rb
        lib/
          custom_plugin/
            issue_custom_field_patch.rb
    

    我们之前说过我们可以使用一些钩子来注入我们想要的功能,但它似乎不适用于控制器。另一方面,我们构建了一个补丁来扩展目标类的功能。

    我们的最终工作代码

    初始化.rb

    require 'redmine'
    ActionDispatch::Callbacks.to_prepare do
      require_dependency 'issue_custom_field'
      unless IssueCustomField.included_modules.include? CustomPlugin::IssueCustomFieldPatch
        IssueCustomField.send(:include, CustomPlugin::IssueCustomFieldPatch)
      end
    end
    
    Redmine::Plugin.register :custom_plugin do
      name 'custom_plugin'
      author 'author name'
      description 'description text'
      version '1.0.0'
    end
    

    issue_custom_field_patch.rb

     module CustomPlugin
        module IssueCustomFieldPatch
            def self.included(base) # :nodoc:
                base.extend(ClassMethods)
                base.send(:include, InstanceMethods)
    
                base.class_eval do 
                    unloadable
                    after_save :update_possible_values
                end
             end
         end
    module ClassMethods
     end
    
     module InstanceMethods
        def update_possible_values
            self.reload
            updatedPossibleValues unless self.name == "Target_CF"
        end
    
        private
         def updatedPossibleValues 
            @safe_attrs = ['project', 'description', 'due_date', 'category', 'status', 'assigned_to', 'priority', 'fixed_version', 'author', 'lock_version', 'created_on', 'updated_on', 'start_date', 'done_ratio', 'estimated_hours', 'is_private', 'closed_on']
             @custom_fields = IssueCustomField.all.select {|cf| !cf[:position].nil?}.collect {|cf| cf.name}
            @possible_values = @safe_attrs + @custom_fields
            CustomField.find_by_name("Target_CF").update possible_values: @possible_values
         end
     end
     CustomField.send(:include, IssueCustomFieldPatch)
    end
    

    功能说明

    正如我们在问题中所述,每次用户从 Redmine 创建/修改/删除自定义字段时,我们都需要更新 Target_CF 的可能值。

    我们扩展了 IssueCustomField 类的实例方法,在每次保存后触发我们的新函数“updatedPossibleValues”。这包括创建新的自定义字段,当然还有更新现有的并删除它们。因为我们每次都重新加载我们的可能值列表,所以我们必须控制它的位置是否为零。如果是,这意味着自定义字段已被删除。

    因为这个补丁的最终动作,是更新另一个自定义字段,这也触发了我们的函数,导致死循环。为了防止这种情况,我们将我们的功能链接到名称不是“Target_CF”的所有其他自定义字段。修复有点生疏,但我们找不到更好的方法。

    我希望这对将来的某些人有用,因为他们可以投入我们在这方面花费的一小部分时间。 非常欢迎评论、修复和改进。

    基于:https://www.redmine.org/projects/redmine/wiki/Plugin_Internals,有点过时了,但终于可以在其他资源和论坛的帮助下完成代码了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 2017-11-21
      • 1970-01-01
      相关资源
      最近更新 更多