※ 本記事は [Redmine Advent Calendar 2020] (https://adventar.org/calendars/5392)の 21 日目の記事です。
初めに
Redmineは、豊富なプラグインによる機能拡張が魅力ですが、ほしい機能のプラグインがないこともあります。そんなときはプラグインの自作に挑戦してみたくなりますよね。
でも、前知識無しでのプラグイン作成は、RubyOnRailsやJavaScriptなどなど、さまざまな知識が必要で、なかなかハードルが高いです。
とりわけ困るのが、Webで見つかるプラグイン作成の入門情報が結構古いものが多いということです。
以下は、代表的なプラグイン作成の入門解説サイトです。
プラグイン チュートリアル - Redmineガイド
最終更新:2014/08/17
対応バージョン: Redmine 2.x
プラグイン開発ガイド - r-labs
最終更新: 2013/03/09
対応バージョン: Redmine 2.1〜2.3
第34回 Redmineプラグイン開発(1):Ruby Freaks Lounge|gihyo.jp … 技術評論社
最終更新: 2010/03/09
対応バージョン: Redmine 0.9.3
Redmineのバージョンによって、各種コマンドや設定方法がかなり変わっているため、上記のサイトのそのままの手順では、うまく行かないことが多いです。
今回は、プラグイン チュートリアル - Redmineガイド について、Redmine バージョン 4.1.1 に対応した差分と、ちょっとした補足を解説したいと思います。
確認環境
- Ruby 2.6.6
- Rails 5.2.4.4
- Redmine 4.1.1
- 作成したプラグイン https://github.com/rbtgr/redmine_plugin_tutorial_polls
プラグインチュートリアル 英語版(原文)について
先述の通り、プラグイン チュートリアル - Redmineガイド は、最終更新:2014/08/17 、対応バージョン: Redmine 2.x となっています。ですが、原文 Plugin Tutorial - Redmine は、最終更新:2020/04/06 対応バージョン: Redmine 4.1.1 となっています。基本的にこちらと見比べながら進めれば良さげです。
以下、各章での、差分のある箇所について記載します。
新しいプラグインの作成
プラグインの新規作成コマンド
# Redmine 2.x
ruby script/rails generate redmine_plugin <plugin_name>
ruby script/rails generate redmine_plugin Polls
# Redmine 3.x ~
bundle exec rails generate redmine_plugin <plugin_name>
bundle exec rails generate redmine_plugin Polls
モデルの作成
init.rb
生成されるファイルの内容に変化があります。
# Redmine 2.x
Redmine::Plugin.register :polls do
name 'Polls plugin'
author 'John Smith'
description 'A plugin for managing polls'
version '0.0.1'
end
# Redmine 3.x ~
Redmine::Plugin.register :polls do
name 'Polls plugin'
author 'Author name'
description 'This is a plugin for Redmine'
version '0.0.1'
url 'http://example.com/path/to/plugin'
author_url 'http://example.com/about'
end
モデル作成コマンド
# Redmine 2.x
ruby script/rails generate redmine_plugin_model <plugin_name> <model_name> [field[:type][:index] field[:type][:index] ...]
ruby script/rails generate redmine_plugin_model polls poll question:string yes:integer no:integer
# Redmine 3.x ~
bundle exec rails generate redmine_plugin_model <plugin_name> <model_name> [field[:type][:index] field[:type][:index] ...]
bundle exec rails generate redmine_plugin_model polls poll question:string yes:integer no:integer
# 生成されるマイグレーションファイ名も変わっています
# Redmine 2.x : 001_create_polls.rb
# Redmine 3.x ~ : xxxxxxxxxxxx_create_polls.rb
マイグレーション実行コマンド
# Redmine 2.x
rake redmine:plugins:migrate
# Redmine 3.x ~
bundle exec rake redmine:plugins:migrate
Rails Console 実行コマンド
# Redmine 2.x
ruby script/rails console
# Redmine 3.x ~
bundle exec rails console
コントローラの作成
コントローラ作成コマンド
# Redmine 2.x
ruby script/rails generate redmine_plugin_controller <plugin_name> <controller_name> [<actions>]
ruby script/rails generate redmine_plugin_controller Polls polls index vote
# Redmine 3.x ~
bundle exec rails generate redmine_plugin_controller <plugin_name> <controller_name> [<actions>]
bundle exec rails generate redmine_plugin_controller Polls polls index vote
polls_controller.rb
class PollsController < ApplicationController
# Redmine 3.x ~ では 'unloadable' は不要。
# unloadable
def index
@polls = Poll.all
end
def vote
poll = Poll.find(params[:id])
poll.vote(params[:answer])
if poll.save
flash[:notice] = 'Vote saved.'
end
# Redmine 2.x
redirect_to :action => 'index'
# Redmine 3.x ~
redirect_to polls_path(project_id: params[:project_id])
end
end
plugins/polls/app/views/polls/index.html.erb
<h2>Polls</h2>
<% @polls.each do |poll| %>
<p>
<%= poll.question %>?
<!-- Redmine 2.x -->
<%= link_to 'Yes', { :action => 'vote', :id => poll[:id], :answer => 'yes' }, :method => :post %> (<%= poll.yes %>) /
<%= link_to 'No', { :action => 'vote', :id => poll[:id], :answer => 'no' }, :method => :post %> (<%= poll.no %>)
<!-- Redmine 3.x ~ -->
<%= link_to 'Yes', { action: 'vote', id: poll[:id], answer: 'yes', project_id: @project }, method: :post %> <%= poll.yes %> /
<%= link_to 'No', { action: 'vote', id: poll[:id], answer: 'no', project_id: @project }, method: :post %> <%= poll.no %>
</p>
<% end %>
アプリケーションメニューの拡張
:application_menu
でメニューが追加される画面が変わっているようです。
-
Redmine 2.x
http://localhost:3000 -
Redmine 3.x ~
http://localhost:3000/projects
プロジェクトメニューの拡張
PollsController
def index
@project = Project.find(params[:project_id])
# Redmine 2.x
@polls = Poll.find(:all) # @project.polls
# Redmine 3.x ~
@polls = Poll.all # @project.polls
end
権限の追加
PollsControllerの変更
# Redmine 2.x
unloadable
before_filter :find_project, :authorize, :only => :index
# Redmine 3.x ~
before_action :find_project, :authorize, only: :index
プラグインの設定画面の追加
プラグインのSettingハッシュ
-
Redmine 2.x
このプラグインの場合、 Setting.plugin_redmine_polls でハッシュにアクセスできます。 -
Redmine 3.x ~
このプラグインの場合、 Setting.plugin_polls でハッシュにアクセスできます。
以降同様に、Setting.plugin_redmine_polls
=> Setting.plugin_polls
プラグイン設定画面
明記はされていないですが、
plugins/polls/app/views/settings/_poll_settings.erb
を作成して、以下の内容を記載する。(<td>
が抜けてます)
<table>
<tbody>
<tr>
<th>Notification Default Address</th>
<td><input type="text" id="settings_notification_default"
value="<%= settings['notification_default'] %>"
name="settings[notification_default]" >
</td>
</tr>
</tbody>
</table>
テストの実行
polls_controller_test.rb の実行方法
# Redmine 2.x
ruby plugins\polls\test\functionals\polls_controller_test.rb
# Redmine 3.x ~ (原文)
RAILS_ENV=test bundle exec rake plugins/polls/test/functionals/polls_controller_test.rb
# 原文では functionals となっているが、生成されるファイルはfunctional
# あと、rake test TEST=ファイル名としないとならないはず・・・
RAILS_ENV=test bundle exec rake test TEST=plugins/polls/test/functional/polls_controller_test.rb
終わりに
ここまでで一通りのチュートリアルの内容は一通り完了です。
ですが、これだけでは少し物足りないですよね。
ということで後編、Redmine プラグインチュートリアル for V4.x系 国際化対応とテスト追加 に続きます。