Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Redmine プラグインチュートリアル for V4.x系

※ 本記事は Redmine Advent Calendar 2020の 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 に対応した差分と、ちょっとした補足を解説したいと思います。

確認環境

プラグインチュートリアル 英語版(原文)について

先述の通り、プラグイン チュートリアル - 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

生成されるファイルの内容に変化があります。

plugins/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

plugins/polls/app/controllers/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

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 でメニューが追加される画面が変わっているようです。

プロジェクトメニューの拡張

PollsController

plugins/polls/app/controllers/polls_controller.rb
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の変更

plugins/polls/app/controllers/polls_controller.rb
# 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>が抜けてます)

plugins/polls/app/views/settings/_poll_settings.erb
<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系 国際化対応とテスト追加 に続きます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away