Redmine3.2プラグイン開発入門の第3弾です!
前回の内容: Redmine3.2プラグイン開発入門 (2) - 既存画面に項目を追加する
今回はRedmine本体のメソッドをカスタマイズします。
Redmineのメソッドをカスタマイズ
前回チケットの参照画面にviewを追加しましたが、チケットに紐づいたテストデータの読込/更新が実装されていませんでした。
そこで今回はRailsの機能であるalias_method_chainを使って既存メソッドをカスタマイズし、チケットデータを読み込む際にテストデータも読み込むようにします。
alias_method_chainの説明はこちらの記事によく書かれているので、本稿ではRedmineのプラグイン開発におけるalias_method_chainの利用方法に説明を絞ります。
modelの作成
まずは読み込み元となるmodelを作成します。
# modelの作成
# issue_id: チケットID, content: テスト内容, result: テスト結果
bundle exec rails g redmine_plugin_model sample Test issue_id:integer content:text result:integer
# マイグレーション
bundle exec rake redmine:plugins:migrate RAILS_ENV=production
patchモジュールの作成
チケットの参照画面の読み込み時にテストデータも同時に読み込むよう、
IssuesControllerクラスのpatchモジュールを作成しshowメソッドに処理を加えます。
module Sample
module IssuesControllerPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
unloadable
alias_method_chain :show, :test
end
end
module InstanceMethods
def show_with_test
# チケットに紐づいたテストデータがあれば取得
@test = Test.find_by(issue_id: @issue.id)
if @test.nil?
# なければ新規作成
@test = Test.create!(issue_id: @issue.id, content: "", result: 0)
end
show = show_without_test
return show
end
end
end
end
モジュールの読み込み
作成したモジュールをinit.rbで読み込みます。
Rails.configuration.to_prepare do
require_dependency 'issues_controller'
# patchモジュールの読み込み
unless IssuesController.included_modules.include? Sample::IssuesControllerPatch
IssuesController.send(:include, Sample::IssuesControllerPatch)
end
end
これでチケットの参照画面にアクセスした際、チケットに紐づいたテストデータがあればそれがロードされ、なければ新規作成されるようになりました。
controllerの作成
次にテストデータを更新する際のcontrollerを作成します。
bundle exec rails g redmine_plugin_controller sample tests
class TestsController < ApplicationController
unloadable
def update
test = Test.find_by(issue_id: params[:issue_id].to_i)
column = "content"
value = params[:value]
if params[:pk].to_i == 2
column = "result"
value = value.to_i
end
if test.update(column => value)
render :nothing => true, :status => 200
else
render :nothing => true, :status => 404
end
end
end
Rails.application.routes.draw do
resources :issues do
post "tests/:id" => "tests#update"
end
end
viewの編集
最後に前回作成したviewを、テストデータの読込/更新に対応するよう修正します。
<hr>
<p><strong>Easy Test</strong></p>
<table id="easy-test">
<tr>
<td>
<p>Content</p>
<a href="#" id="test-content"><% if @test.content == "" %>Empty<% else %><%= @test.content %><% end %></a>
</td>
<td>
<p>Result</p>
<a href="#" id="test-result">
<% if @test.result == 0 %>-<% elsif @test.result == 1 %>OK<% else %>NG<% end %>
</a>
</td>
</tr>
</table>
<input id="test-id" type="hidden" value="<%= @test.id %>">
<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/jquery-editable/css/jquery-editable.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/jquery-editable/js/jquery-editable-poshytip.min.js"></script>
<style type="text/css">
table#easy-test {
width: 100%;
}
table#easy-test tr td:first-child {
width: 66%;
}
table#easy-test tr td:last-child {
width: 34%;
vertical-align: top;
}
div.editable-input textarea {
width: 500px;
}
div.editable-input select {
width: 100px;
}
</style>
<script>
$(function() {
$.fn.editable.defaults.url = window.location.href + '/tests/' + $("#test-id").val();
$.fn.editable.defaults.mode = 'inline';
$.fn.editable.defaults.showbuttons = 'bottom';
$('#test-content').editable({
type: 'textarea',
pk: 1
});
$('#test-result').editable({
type: 'select',
pk: 2,
source: [
{ value: 0, text: '-' },
{ value: 1, text: 'OK' },
{ value: 2, text: 'NG' }
]
});
});
</script>
以上で完成です!
第2,3回全体のソースはGitHubのリポジトリに置いていますので、よろしければ参考にしてください。
終わりに
駆け足でRedmineのプラグイン開発方法について紹介しましたが、
Railsのコールバックを利用する方法等、まだまだ紹介できていないことがあります。
ぜひご自分で調べて、実際に使ってみてください!