Как вызвать функцию, когда пользовательское поле редактируется / создается в Redmine - PullRequest
0 голосов
/ 07 апреля 2020

Я изучал этот термин так много часов, но пока что нашел что-то полезное. Надеюсь, вы поможете нам создать этот плагин redmine или предоставите нам несколько ссылок на исследования, которые помогут нам найти правильный ключ.

Что мы хотим построить

Дело в том, что мы хотим обновить один кастом поле в redmine (назовем его 'Target_CF') всякий раз, когда другой создается или обновляется. Мы ищем приращение возможных значений Target_CF, чтобы у нас были все имена настраиваемых полей для выбора. Конечно, мы хотим достичь этого без непосредственного редактирования ядра Redmine, поэтому мы подумали, что разработка плагина будет лучшим подходом.

Наш плагин также создает и настраивает новое настраиваемое поле (упомянутое выше), но Я позволю это исключить, потому что я думаю, что это не имеет отношения к этому.

Где мы находимся сейчас

Мы определили некоторые крючки, которые могут быть полезны для нас, как следующее:

  • : 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

Результатом этого кода является none. Я имею в виду, никаких ошибок, никаких обновлений, вообще ничего. Наши возможные значения не меняются после редактирования / создания другого настраиваемого поля. Мы уверены, что есть что-то, чего мы не знаем, какая-то концепция или рабочий процесс, и из-за этого мы делаем что-то очень плохо. Пожалуйста, помогите нам понять, чего нам не хватает.

Ранее мы успешно разработали еще один плагин, который перезаписывает определенные представления. Таким образом, у нас есть немного навыков в виде плагинов, связанных с представлениями, но совсем нет опыта работы с контроллерами.

Мы используем стек Redmine 3.2.0 от Bitnami и базу данных mysql.

1 Ответ

0 голосов
/ 08 апреля 2020

Ну, наконец-то мы узнали, как расширить методы базового контроллера. Я опубликую это здесь так, я надеюсь, что это может быть полезно для любого, кто находит те же самые сомнения, которые у нас были. После еще нескольких исследований мы пришли к выводу, что расширение базовых контроллеров является обязательным, чтобы напрямую не изменять основные методы.

Это наши окончательные структуры каталогов / файлов:

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

Мы ранее заявляли, что можем использовать некоторые хуки для внедрения желаемой функциональности, но, похоже, это не работает с контроллерами. С другой стороны, мы создали патч, который расширит функциональность целевого класса.

Наш окончательный рабочий код

Init.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

Объяснение функциональности

Как мы указали в вопросе, нам нужно было обновлять возможные значения Target_CF каждый раз, когда пользователи создают / изменяют / удаляют настраиваемые поля из Redmine.

Мы расширенные методы экземпляра класса IssueCustomField, вызывающие нашу новую функцию updatedPossibleValues ​​после каждого сохранения. Это включает в себя создание новых пользовательских полей и, конечно же, обновление существующих и удаление их. Поскольку мы каждый раз перезагружаем наш список возможных значений, нам приходилось контролировать, была ли его позиция нулевой. Если это так, это означает, что пользовательское поле было удалено.

Из-за окончательного действия этого патча, которое является обновлением другого настраиваемого поля, это также вызвало нашу функцию, вызвав бесконечное l oop. Чтобы предотвратить это, мы связали нашу функциональность с любым другим настраиваемым полем, имя которого не было «Target_CF». Немного ржавое исправление, но мы не смогли найти лучший подход.

Я надеюсь, что это может пригодиться кому-то в будущем, так как они могли бы потратить часть времени, которую мы потратили на это. Комментарии, исправления и улучшения приветствуются.

Основано на: https://www.redmine.org/projects/redmine/wiki/Plugin_Internals, которое немного устарело, но в итоге может дополнить код с помощью других ресурсов и форумов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...