Redmine3.3でIssueExtensionsを動かす


Redmine2からRedmine3にアップグレード

Redmine3ではIssueExtensionsプラグインが動作しないため試行錯誤してなんとか動くようになった。
なお、RubyもRaisも全くしらないので全て信用しないで頂きたい。

Environment:
  Redmine version                3.3.0.stable.15663
  Ruby version                   2.2.5-p319 (2016-04-26) [x86_64-linux]
  Rails version                  4.2.6
  Environment                    production
  Database adapter               Mysql2

ベースとするIssueExtensions

http://www.r-labs.org/projects/issueext を使っていたが
https://github.com/planio-gmbh/edmine_issue_extensions にしてみる。

初期設定

Redmine2からRedmine3へのマイグレーションでエラー

メッセージを残し忘れていたが以下のようなエラーだったかと…

An error occurred while loading the routes definition of redmine_issue_extensions plugin (/var/lib/redmine-3.3/plugins/redmine_issue_extensions/config/routes.rb): You should not use the `match` method in your router without specifying an HTTP method.
If you want to expose your action to both GET and POST, add `via: [:get, :post]` option.
If you want to expose your action to GET, use `get` in the router:
  Instead of: match "controller#action"
  Do: get "controller#action".
redmine_issue_extensions/config/routes.rb
*** 17,22 ****

  RedmineApp::Application.routes.draw do
    match 'issue_extensions/:action', :controller => 'issue_extensions', :via => [:get, :post]
!   match 'issue_extensions_settings/:action', :controller => 'issue_extensions_settings'
    match 'issue_relations/:action', :controller => 'issue_relations', :via => [:get, :post]
  end
--- 17,22 ----

  RedmineApp::Application.routes.draw do
    match 'issue_extensions/:action', :controller => 'issue_extensions', :via => [:get, :post]
!   match 'issue_extensions_settings/:action', :controller => 'issue_extensions_settings', :via => [:get, :post, :put, :patch]
    match 'issue_relations/:action', :controller => 'issue_relations', :via => [:get, :post]
  end

プロジェクトの設定画面が開かない

ActiveRecord::RecordNotFound (Couldn't find all IssueExtensionsStatusFlows with 'id': (first, {:conditions=>["project_id = ?", 2]}) (found 0 results, but was looking for 2)):
  plugins/redmine_issue_extensions/app/models/issue_extensions_status_flow.rb:21:in `find_or_create'
  plugins/redmine_issue_extensions/app/views/issue_extensions_settings/_show.html.erb:21:in `_plugins_redmine_issue_extensions_app_views_issue_extensions_settings__show_html_erb__2241146892683185007_70191963673200'
redmine_issue_extensions/app/models/issue_extensions_status_flow.rb
*** 18,24 ****
    belongs_to :project

    def self.find_or_create project_id, user_id
!     status_flow = IssueExtensionsStatusFlow.find :first, :conditions => ['project_id = ?', project_id]
      unless status_flow
        status_flow = IssueExtensionsStatusFlow.new
        status_flow.project_id = project_id
--- 18,24 ----
    belongs_to :project

    def self.find_or_create project_id, user_id
!     status_flow = IssueExtensionsStatusFlow.find_by :project_id => project_id
      unless status_flow
        status_flow = IssueExtensionsStatusFlow.new
        status_flow.project_id = project_id
ActiveRecord::RecordNotFound (Couldn't find all IssueStatuses with 'id': (all, {:order=>"position"}) (found 0 results, but was looking for 2)):
  plugins/redmine_issue_extensions/app/views/issue_extensions_settings/_show.html.erb:22:in `_plugins_redmine_issue_extensions_app_views_issue_extensions_settings__show_html_erb___3067774532135620242_70290714364540'
redmine_issue_extensions/app/views/issue_extensions_settings/_show.html.erb
*** 19,25 ****
  <div id="issue_extension_settings">
  <%
  @issue_extension_status_flow = IssueExtensionsStatusFlow.find_or_create(@project.id, User.current.id)
! @statuses = IssueStatus.find(:all, :order => 'position') %>
  <%= labelled_form_for :setting, @issue_extension_status_flow,
                               :url => {:controller => 'issue_extensions_settings',
                                 :action => 'update', :id => @project, :tab => 'issue_extensions',
--- 19,25 ----
  <div id="issue_extension_settings">
  <%
  @issue_extension_status_flow = IssueExtensionsStatusFlow.find_or_create(@project.id, User.current.id)
! @statuses = IssueStatus.order(:position) %>
  <%= labelled_form_for :setting, @issue_extension_status_flow,
                               :url => {:controller => 'issue_extensions_settings',
                                 :action => 'update', :id => @project, :tab => 'issue_extensions',

IssueExtensionsの設定画面での更新でエラー

ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError):
  plugins/redmine_issue_extensions/app/controllers/issue_extensions_settings_controller.rb:25:in `update'
redmine_issue_extensions/app/controllers/issue_extensions_settings_controller.rb
*** 21,26 ****
--- 21,27 ----
    before_filter :find_project, :find_user, :authorize

    def update
+     params.permit!
      @issue_extension_status_flow = IssueExtensionsStatusFlow.find_or_create(@project.id, @user.id)
      @issue_extension_status_flow.attributes = params[:setting]
      @issue_extension_status_flow.updated_by = @user.id

チケットの編集(保存)でのエラー

ActiveRecord::RecordNotFound (Couldn't find all IssueExtensionsStatusFlows with 'id': (first, {:conditions=>["project_id = ?", 5]}) (found 0 results, but was looking for 2)):
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:61:in `issue_status_assigned'
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:31:in `controller_issues_edit_before_save'
redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb
*** 58,64 ****
    # チケットに担当者が設定されている && 状態が新規の場合、担当に変更する
    def issue_status_assigned context
      issue = context[:issue]
!     issue_status = IssueExtensionsStatusFlow.find :first, :conditions => ['project_id = ?', issue[:project_id].to_i]

      if issue_status.old_status_id == issue[:status_id]
          issue[:status_id] = issue_status.new_status_id
--- 58,64 ----
    # チケットに担当者が設定されている && 状態が新規の場合、担当に変更する
    def issue_status_assigned context
      issue = context[:issue]
!     issue_status = IssueExtensionsStatusFlow.find_by :project_id => issue[:project_id].to_i

      if issue_status.old_status_id == issue[:status_id]
          issue[:status_id] = issue_status.new_status_id
ActiveRecord::RecordNotFound (Couldn't find all IssueStatuses with 'id': (all, {:conditions=>["is_closed = (?)", true]}) (found 0 results, but was looking for 2)):
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:72:in `issue_status_closed'
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:32:in `controller_issues_edit_before_save'
redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb
*** 69,75 ****
    # チケットがクローズされている場合、進捗を100%に変更する
    def issue_status_closed context
      issue = context[:issue]
!     issue_status_closed = IssueStatus.find :all, :conditions => ["is_closed = (?)", true]

      issue_status_closed.each {|closed|
        if closed.id == issue[:status_id].to_i && issue[:done_ratio] != 100
--- 69,75 ----
    # チケットがクローズされている場合、進捗を100%に変更する
    def issue_status_closed context
      issue = context[:issue]
!     issue_status_closed = IssueStatus.where("is_closed = true")

      issue_status_closed.each {|closed|
        if closed.id == issue[:status_id].to_i && issue[:done_ratio] != 100
ActiveRecord::RecordNotFound (Couldn't find all Watchers with 'id': (first, {:conditions=>false}) (found 0 results, but was looking for 2)):
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:87:in `issue_added_watcher'
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:33:in `controller_issues_edit_before_save'
redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb
*** 84,90 ****
      issue = context[:issue]
      journal = context[:journal]

!     if Watcher.find :first, :conditions =>["watchable_type = (?) and watchable_id = (?) and user_id = (?)", journal[:journalized_type], issue[:id].to_i, journal[:user_id].to_i] == nil
          hash_watcher = HashWithIndifferentAccess.new
          hash_watcher[:user_id]  = journal[:user_id].to_s
          watcher = Watcher.new(hash_watcher)
--- 84,90 ----
      issue = context[:issue]
      journal = context[:journal]

!     if Watcher.where("watchable_type = (?) and watchable_id = (?) and user_id = (?)", journal[:journalized_type], issue[:id].to_i, journal[:user_id].to_i).first == nil
          hash_watcher = HashWithIndifferentAccess.new
          hash_watcher[:user_id]  = journal[:user_id].to_s
          watcher = Watcher.new(hash_watcher)

各機能の動作

自動アサイン機能

使用していないので未確認。

自動クローズ機能

ここまでの変更で問題なし。

自動ウォッチャー機能

ここまでの変更で問題なし。

関連するチケット作成機能

エラーとなったため対応。

ActiveRecord::RecordNotFound (Couldn't find all Issues with 'id': (first, {:conditions=>["id = (?)", 1034]}) (found 0 results, but was looking for 2)):
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:101:in `issue_added_relation'
  plugins/redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb:53:in `controller_issues_new_after_save'
redmine_issue_extensions/lib/issue_extensions_issue_hooks.rb
*** 98,104 ****
    def issue_added_relation context
      issue = context[:issue]
      params = context[:params]
!     from_issue = Issue.find :first, :conditions =>["id = (?)", params[:relation_issue_id].to_i]
      unless from_issue == nil
        relation = IssueRelation.new
        relation.relation_type = IssueRelation::TYPE_RELATES
--- 98,104 ----
    def issue_added_relation context
      issue = context[:issue]
      params = context[:params]
!     from_issue = Issue.find_by :id => params[:relation_issue_id].to_i
      unless from_issue == nil
        relation = IssueRelation.new
        relation.relation_type = IssueRelation::TYPE_RELATES

チケット検索機能

この機能は使ったことがない。有効なのか?

  • チケットに表示されている「題名」の隣のテキストボックスに検索したいチケットの題名を記入し、「適用」をクリックします。
  • 検索結果が、「ヒットしたチケット」中に表示されるので、関連付けしたいチケットの関連付けアイコンをクリックすると関連付けされます。
    • 関連付け以外(重複やブロック、先行・後続)は表示されているチケット番号を参考に行ってください。

ショートカット機能

ここまでの変更で問題なし。

新規複製機能

Processing by IssuesController#new as HTML
  Parameters: {"duplicate_issue"=>"t", "project_id"=>"5", "copy_from"=>"1034"}
  Current user: foo (id=3)
  Rendered common/error.html.erb within layouts/base (0.1ms)
  Rendered plugins/redmine_code_review/app/views/code_review/_html_header.html.erb (0.1ms)
  Rendered plugins/redmine_wiki_extensions/app/views/wiki_extensions/_html_header.html.erb (0.0ms)
  Rendered plugins/sidebar_hide/app/views/sidebar/_hideButton_partial.html.erb (0.3ms)
  Rendered plugins/redmine_code_review/app/views/code_review/_body_bottom.html.erb (0.0ms)
  Rendered plugins/redmine_wiki_extensions/app/views/wiki_extensions/_body_bottom.html.erb (0.0ms)
Completed 403 Forbidden in 136ms (Views: 13.1ms | ActiveRecord: 62.6ms)

ロールと権限の設定で「チケットのコピー」を行う権限がなかったため。
権限を追加したことろ問題なし。