前回(Redmineプラグイン作成でHookを使ってみる(続) - torutkのブログ)は、RedmineプラグインでView hooksの実装(HTMLテンプレート)において、コントローラークラスのインスタンス変数を利用する方法について記述しました。
今回は、既存のモデルをHTMLテンプレート内で利用する方法を調べてみました。
プロジェクトの概要ページのチケットトラッキング
Redmineで[概要]メニューを開くと、「チケットトラッキング」が表示されます。
しかし、ステータスごとの件数ではなく、未完了か完了かで集計されてしまいます。完了は、通常は[終了]または[却下]のステータスとなり、それ以外は未完了となります。
ステータス毎の集計を見たい場合、標準ではその画面が見当たらないので、プラグインを作って対応してみます。
チケットの件数を取得する方法
Railsでは、モデルにcountというメソッドがあり、SQLのSELECT COUNT(*)相当の機能となります。
最初、HTMLテンプレート(.erb)では、モデルへのアクセスが出来ないと思い、コントローラを作ってみましたが、試行錯誤してみたところできることが分かりました。
Redmine標準のプロジェクトの概要ページの表示では、次の方法でチケットの完了/未完了/合計の件数を取得しています。
- redmine/app/controllers/projects_controller.rb
class ProjectsController < ApplicationController : def show : cond = @project.project_condition(Setting.display_subprojects_issues?) @open_issues_by_tracker = Issue.visible.open.where(cond).group(:tracker).count @total_issues_by_tracker = Issue.visible.where(cond).group(:tracker).count
チケットのモデルクラスIssueを使って、指定したトラッカーのチケットで、アクセス可能なチケットのオープン(未完了)のチケット件数と合計のチケット件数を取得しています。
visibleは、アクセスしているユーザーが閲覧できるチケットを対象としています。
whereの指定方法には幾つかの形式があり悩みました。
あちこちを見て回ったところ、次のようにハッシュ形式で条件を入れるのが分かりやすく簡潔でよさそうです。
- redmine/app/models/issue_status.rb
Issue.where(:status_id => id, :closed_on => nil)
groupを使うとグループに指定した属性ごとの集計ができ、属性名をハッシュのキーとして値が取り出せるハッシュが得られるようです。
上述の例では、@open_issues_by_tracker[tracker] という式で指定したトラッカーの未完了の件数を取り出しています。
プロジェクトの概要のView hooksでステータス毎のチケット件数を表示する
フック名は、:view_projects_show_left になります。そこで、先日作成したプラグインのhook.rbに追記します。
- plugins/redmine_issues_kpi/lib/hooks.rb
module RedmineIssuesKpi class Hooks < Redmine::Hook::ViewListener render_on :view_issues_index_bottom, :partial => 'issuesIndexBottom' render_on :view_projects_show_left, :partial => 'projectsShowLeft' end end
パーシャル(HTMLテンプレート)を作成します。
- plugins/redmine_issues_kpi/views/projects/_projectsShowLeft.html.erb
<h3>チケット数内訳</h3> <% if @trackers.present? %> <% @trackers.each do |tracker| %> <h4><%= tracker.name %></h4> <table class="list"> <thead> <tr> <% tracker.issue_statuses.each do |status| %> <th><%= status.name %></th> <% end %> </tr> </thead> <tbody> <tr> <% num_issues_by_status = Issue.visible.where(:project_id => @project.id, :tracker_id => tracker.id).group(:status).count %> <% tracker.issue_statuses.each do |status| %> <td><%= num_issues_by_status[status].to_i %></td> <% end %> </tr> </tbody> </table> <% end %> <% end %>
とりあえずべたに記述してみました。
コントローラー(redmine/app/controllers/projects_controller.rb)で定義されたインスタンス変数を活用しています。
HTMLテンプレートでは、ロジックの記述に<% ... %>と、<%= ... %>があり、前者はロジックの実行(評価)だけを行い、後者はロジックの評価をHTMLに置き換えます。
@trackers にあるトラッカーそれぞれについて、ステータス毎のチケット件数をIssueクラスのメソッドで取得しています。