Help us understand the problem. What is going on with this article?

Rails を知らない人のための Redmine プラグイン開発ガイド for Bitnami Redmine 3.4 & Redmine4.0

はじめに

この記事は,Redmine プラグイン作成ガイド「r-labs | Rails を知らない人のための Redmine プラグイン開発ガイド」を Redmine3.4 & Redmine4.0 で実行した際に,Ruby, Rails 初心者の私がつまずいて変更した点をまとめたものです.元記事に対して変更の必要がないと判断した部分は変更なしと記しました.
ハッシュの記法はプラグイン開発ガイドに倣い,:key => value で統一しています.

プラグイン開発ガイド元記事(Redmine 2.1〜2.3 を前提):
https://www.r-labs.org/projects/r-labs/wiki/プラグイン開発ガイド

環境

  • Windows 10 64bit Ver.1903
  • Bitnami Redmine Stack 3.4.6-5
    • Rails 4.2.8
    • ruby 2.3.3p222 (2016-11-21 revision 56859) [i386-mingw32]
  • Bitnami Redmine Stack 4.0.3-3
    • Rails 5.2.2.1
    • ruby 2.5.5p157 (2019-03-15 revision 67260) [x64-mingw32]
    • (私の環境では最新の Bitnami Redmine Stack 4.0.4 を動作させることが出来ませんでした.)

Redmine3.4(Rails4.2) と Redmine4.0(Rails5.2) での変更点

  1. マイグレーションファイルの修正
  2. before_filter メソッドの廃止に伴い,before_action メソッドを利用

目次(プラグイン開発ガイドより)

  1. はじめに
  2. プラグイン開発環境の準備
  3. Rails の概要
  4. サンプルプラグインの仕様
  5. プラグインスケルトンの生成
  6. init.rb の作成
  7. モデルのスケルトンの生成
  8. コントローラのスケルトンの生成
  9. プロジェクトで利用可能にする
  10. 国際化
  11. 一覧表示 アクション
  12. 新規作成 アクション
  13. その他のアクション(詳細表示、編集フォーム、更新、削除、プレビュー)
  14. まとめ

r-labs プラグイン開発ガイドを bitnami Redmine 3.4 へ適用した際の変更点まとめ

1. はじめに

変更なし

2. プラグイン開発環境の準備

開発用 Redmine のポイント

変更なし

使用ソフト

この記事では Bitnami Redmine を使用しました.
https://bitnami.com/stack/redmine/installer

gem パッケージのインストール

実行しません.

データベース設定

以下の記事を参考にさせていただき,development モードで起動させるためのデータベースの設定を進めます.

参考: Redmine pluginの開発について当初自分が疑問に思ってたことに回答 - Qiita

疑問2 どうやってdevelopmentモードやtestモードで動かすの?
1. コンソールを起動
C:\Bitnami\redmine-3.4.6-5\use_redmine.bat
cd .\apps\redmine\htdocs
2. Redmineをdevelopmentモードで起動する

  1. 起動中のサービスを停止
    → 停止しなくても問題ない
  2. 相対パスの無効化
  3. development用、test用bundle設定有効化
    → development だけ除く

    .\.bundle\config
    BUNDLE_WITHOUT: test:sqlite
    
  4. bundle実行

  5. DB設定を確認

    .\config\database.yml
    production:
      adapter: mysql2
      database: bitnami_redmine
      host: 127.0.0.1
      username: bitnami
      password: de0166b709  # インストール時に自動生成
      encoding: utf8
      port: 3306
    development:
      adapter: mysql2
      database: bitnami_redmine
      host: 127.0.0.1
      username: bitnami
      password: de0166b709  # インストール時に自動生成
      encoding: utf8
      port: 3306
    

データベースの作成

Bitnami インストール時に作成済みのため実行しません.

サーバの起動

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> bundle exec rails s

localhost:3000 へアクセスすると Redmine が表示されます.

image.png

補足: log について

development 環境では,↑のように Terminal で log が確認出来ますが,logファイル(.\log\development.log )も参考になりました.個人的に,Terminal 上の出力結果は,画面端で文字が折返されてしまうために文字の列が揃っておらず見難いと感じています.

3. Rails の概要

変更なし

4. サンプルプラグインの仕様

変更なし

5. プラグインスケルトンの生成

プラグイン名前を決める

変更なし(ガイドと同じく redmine_standard とします)

スケルトン

変更なし

スケルトン作成コマンドの実行

ruby script/railsbundle exec rails

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> bundle exec rails generate redmine_plugin redmine_standard
実行結果
      create  plugins/redmine_standard/app
      create  plugins/redmine_standard/app/controllers
      create  plugins/redmine_standard/app/helpers
      create  plugins/redmine_standard/app/models
      create  plugins/redmine_standard/app/views
      create  plugins/redmine_standard/db/migrate
      create  plugins/redmine_standard/lib/tasks
      create  plugins/redmine_standard/assets/images
      create  plugins/redmine_standard/assets/javascripts
      create  plugins/redmine_standard/assets/stylesheets
      create  plugins/redmine_standard/config/locales
      create  plugins/redmine_standard/test
      create  plugins/redmine_standard/test/fixtures
      create  plugins/redmine_standard/test/unit
      create  plugins/redmine_standard/test/functional
      create  plugins/redmine_standard/test/integration
      create  plugins/redmine_standard/README.rdoc
      create  plugins/redmine_standard/init.rb
      create  plugins/redmine_standard/config/routes.rb
      create  plugins/redmine_standard/config/locales/en.yml
      create  plugins/redmine_standard/test/test_helper.rb

プラグインのディレクトリ構成

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> tree /F plugins/redmine_standard
実行結果
│  init.rb
│  README.rdoc
│
├─app
│  ├─controllers
│  ├─helpers
│  ├─models
│  └─views
├─assets
│  ├─images
│  ├─javascripts
│  └─stylesheets
├─config
│  │  routes.rb
│  │
│  └─locales
│          en.yml
│
├─db
│  └─migrate
├─lib
│  └─tasks
└─test
    │  test_helper.rb
    │
    ├─fixtures
    ├─functional
    ├─integration
    └─unit

6. init.rb の作成

変更なし

7. モデルのスケルトンの生成

データベース

変更なし

モデルの名前とデータ構成を決める

変更なし

モデルスケルトンの生成

ruby script/railsbundle exec rails

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> bundle exec rails generate redmine_plugin_model redmine_standard foo project_id:integer subject:string description:text
実行結果
      create  plugins/redmine_standard/app/models/foo.rb
      create  plugins/redmine_standard/test/unit/foo_test.rb
      create  plugins/redmine_standard/db/migrate/001_create_foos.rb

生成された Migration 用のファイル

Redmine 3.4

変更なし

Redmine 4.0

Redmine 3.4 (Rails 4.2) と同じ記述ではエラーが発生し,マイグレーションを完了できません.

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
>bundle exec rake redmine:plugins:migrate
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:

  class CreateFoos < ActiveRecord::Migration[4.2]

これは,Rails 5.1 以降 Migration versioning により,対象とするバージョンの記載が必須となったため...だそうです.
参考: Rails Migration versioningと5.1での変更点 - chulip.org

警告メッセージにある通り変更します.

.\plugins\redmine_standard\db\migrate\001_create_foos.rb
# class CreateFoos < ActiveRecord::Migration  # Rails 4.2
class CreateFoos < ActiveRecord::Migration[4.2]  # Rails 5.2
    def change
        create_table :foos do |t|
            t.integer :project_id
            t.string :subject
            t.text :description
        end
    end
end

Migration の実行

ruby script/railsbundle exec rails

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> bundle exec rake redmine:plugins:migrate
実行結果
Migrating redmine_standard (Redmine Standard plugin)...
== 1 CreateFoos: migrating ====================================================
-- create_table(:foos)
   -> 0.0322s
== 1 CreateFoos: migrated (0.0339s) ===========================================

※Migration の実行時にRAILS_ENVオプションをつけない場合,development環境に対してテーブルが作成されます.(参考: rake db:migrate - リファレンス - - Railsドキュメント
本来であればproduction環境にテーブルを作成するにはRAILS_ENV=productionオプションをつける必要がありますが,今回はproduction環境とdevelopment環境のDBを同一として設定したため,development環境でfoosテーブルを作ればproduction環境でもfoosテーブルが使えることになります.

生成された Model のファイル

変更なし

プラグインのテーブルの削除

変更なし

sqlite3 によるデータベースの操作

Bitnami Redmine は MySQL のため,MySQLに置き換えて考えます.

データベース一覧表示

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> mysql -u root -p
mysql> show databases;
実行結果
+--------------------+
| Database           |
+--------------------+
| information_schema |
| bitnami_redmine    |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

bitnami_redmine テーブル一覧表示

foos テーブルが作られている事が確認できます

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
mysql> show tables from bitnami_redmine;
実行結果(一部省略)
+-------------------------------------+
| Tables_in_bitnami_redmine           |
+-------------------------------------+
| attachments                         |
| auth_sources                        |
        :
| enabled_modules                     |
| enumerations                        |
| foos                                |
| groups_users                        |
| import_items                        |
        :
| wikis                               |
| workflows                           |
+-------------------------------------+
56 rows in set (0.00 sec)

8. コントローラのスケルトンの生成

コントローラ、アクションの名前を決める

変更なし(ガイドと同一とします)

コントローラのスケルトン作成コマンドの実行

ruby script/railsbundle exec rails

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> bundle exec rails generate redmine_plugin_controller redmine_standard foos index new show edit
実行結果
      create  plugins/redmine_standard/app/controllers/foos_controller.rb
      create  plugins/redmine_standard/app/helpers/foos_helper.rb
      create  plugins/redmine_standard/test/functional/foos_controller_test.rb
      create  plugins/redmine_standard/app/views/foos/index.html.erb
      create  plugins/redmine_standard/app/views/foos/new.html.erb
      create  plugins/redmine_standard/app/views/foos/show.html.erb
      create  plugins/redmine_standard/app/views/foos/edit.html.erb

コントローラの生成ファイル

変更なし

ビューの生成ファイル

変更なし

Erb (Embeded ruby)

変更なし

9. プロジェクトで利用可能にする

モジュールと permission の設定

変更なし

プラグインメニューへの追加

変更なし

URL の指定方法

変更なし

Rails の機能

変更なし

ルーティング

ルーティングの設定

後に preview_link メソッドにより使用することになる preview URLは,PATCH メソッドで処理されるため,put 'preview', :on => :memberpatch 'preview', :on => :member へ変更します.
post 'preview', :on => :collection は,元記事のガイドでは使用していないので検証しませんでした.)

.\plugins\redmine_standard\config\routes.rb
# Plugin's routes
# See: http://guides.rubyonrails.org/routing.html

Rails.application.routes.draw do
    resources :projects do
        resources :foos do
            post  'preview', :on => :collection
            # put   'preview', :on => :member  # プラグイン開発ガイドに記載されている設定
            patch 'preview', :on => :member  # プラグイン開発ガイドより変更
        end
    end
end

ルーティングの確認

ruby script/railsbundle exec rails

C:\Bitnami\redmine-3.4.6-5\apps\redmine\htdocs
> bundle exec rake routes
実行結果(プラグインに関する部分のみ抜粋)
                                Prefix Verb               URI Pattern                                                                       Controller#Action
                  preview_project_foos POST               /projects/:project_id/foos/preview(.:format)                                      foos#preview
                   preview_project_foo PATCH              /projects/:project_id/foos/:id/preview(.:format)                                  foos#preview
                          project_foos GET                /projects/:project_id/foos(.:format)                                              foos#index
                                       POST               /projects/:project_id/foos(.:format)                                              foos#create
                       new_project_foo GET                /projects/:project_id/foos/new(.:format)                                          foos#new
                      edit_project_foo GET                /projects/:project_id/foos/:id/edit(.:format)                                     foos#edit
                           project_foo GET                /projects/:project_id/foos/:id(.:format)                                          foos#show
                                       PATCH              /projects/:project_id/foos/:id(.:format)                                          foos#update
                                       PUT                /projects/:project_id/foos/:id(.:format)                                          foos#update
                                       DELETE             /projects/:project_id/foos/:id(.:format)                                          foos#destroy
Prefix Verb URI Pattern Controller#Action
preview_project_foos POST /projects/:project_id/foos/preview(.:format) foos#preview
preview_project_foo PATCH /projects/:project_id/foos/:id/preview(.:format) foos#preview
project_foos GET /projects/:project_id/foos(.:format) foos#index
POST /projects/:project_id/foos(.:format) foos#create
new_project_foo GET /projects/:project_id/foos/new(.:format) foos#new
edit_project_foo GET /projects/:project_id/foos/:id/edit(.:format) foos#edit
project_foo GET /projects/:project_id/foos/:id(.:format) foos#show
PATCH /projects/:project_id/foos/:id(.:format) foos#update
PUT /projects/:project_id/foos/:id(.:format) foos#update
DELETE /projects/:project_id/foos/:id(.:format) foos#destroy

index ページの表示

変更なし

@project の設定

変更なし

before_filter

Redmine 3.4

変更なし

Redmine 4.0

before_filter を使用するとエラーとなります.
(ブラウザ上でエラーの詳細内容を確認出来ます)
Routing Error

警告メッセージの通りbefore_actionに変更します.

.\htdocs\plugins\redmine_standard\app\controllers\foos_controller.rb
class FoosController < ApplicationController
    unloadable
    menu_item :standard
    # before_filter :find_project, :authorize  # Rails 4.2
    before_action :find_project, :authorize  # Rails 5.2
    # before_filter :find_foo, :except => [:index, :new, :create, :preview]  # Rails 4.2
    before_action :find_foo, :except => [:index, :new, :create, :preview]  # Rails 5.2
    :

authorize

変更なし

途中経過①

標準プラグインIndex(index アクション)

image.png

プロジェクト > モジュール設定ページ

image.png

管理 > ロールと権限 設定ページ

image.png

10. 国際化

変更なし

11. 一覧表示 アクション

ページ表示の流れ

変更なし

コントローラの実装

Foo.find の代わりに Foo.where を使用します.

.\plugins\redmine_standard\app\controllers\foos_controller.rb
  def index
    # @foos = Foo.find(:all, :conditions => ["project_id = #{@project.id} "])  # プラグイン開発ガイドに記載されているスクリプト
    # データが空の場合↓のようなエラーが発生する
    # Couldn't find all Foos with 'id': (all, {:conditions=>["project_id = 1 "]}) (found 0 results, but was looking for 2)

    @foos = Foo.where("project_id = #{@project.id}")  # エラー対策
  end

ビューの実装

変更なし

一覧表示ページ

変更なし

途中経過②

標準プラグインIndex(index アクション)

image.png

12. 新規作成(new)アクション

新規作成ページの仕様

変更なし

GET と POST と PUT

変更なし

コントローラの実装

params[:foo]params[:foo].permit(:subject, :description) とします.
参考: 【Rails】パラメータからcreateするときにはまったところメモ - Qiita

.\plugins\redmine_standard\app\controllers\foos_controller.rb
  def create
    # @foo = Foo.new(params[:foo])  # プラグイン開発ガイドに記載されているスクリプト
    # ↓のようなエラーが発生する
    # ActiveModel::ForbiddenAttributesError

    @foo = Foo.new(params[:foo].permit(:subject, :description))  # エラー対策
    @foo.project_id = @project.id

    if @foo.save    
      flash[:notice] = l(:notice_successful_create)
      redirect_to project_foo_path(@project, @foo.id)
    end
  end

その他のエラー

create メソッドを追加したにも関わらず AbstractController::ActionNotFound (The action 'create' could not be found for FoosController) エラーが発生する場合,create メソッドが private メソッドになっている可能性があります.(私は一度ミスしました….)

ビューの実装

変更なし

モデルの実装

変更なし

途中経過③

新規作成(new アクション)

image.png

作成完了(create アクション)

image.png

13. その他のアクション(詳細表示、編集フォーム、更新、削除、プレビュー)

Foo オブジェクト(@foo)の取得

変更なし

詳細表示(show アクション)

:confirm => l(:text_are_you_sure):data => {:confirm => l(:text_are_you_sure)} とします.
:confirm => はRails4.1で廃止された模様です.
(参考: Redmine 4.0(Rails 5.1)でのプラグイン作成について - torutkのブログ

.\plugins\redmine_standard\app\views\foos\show.html.erb
<h2><%=h l(:label_foo) %>#<%= @foo.id %></h2>

<div class="issue">      

  <div class="subject">
    <h3><%= @foo.subject %></h3>
  </div>

<% unless @foo.description.blank? %>
  <p><strong><%=l(:field_description)%></strong></p>
  <div class="wiki">
    <%= textilizable @foo.description %>
  </div>
<% end %>

</div>

<div class="contextual">
<%= link_to_if_authorized(l(:button_edit),
                          {:action => 'edit', :project_id => @project, :id => @foo.id},
              :class => 'icon icon-edit') %>
<%= link_to_if_authorized(l(:button_delete),
                          {:action => 'destroy', :project_id => @project, :id => @foo.id},
                # :confirm => l(:text_are_you_sure),  # Rails4.1で廃止
               :data => {:confirm => l(:text_are_you_sure)},  # 対策
               :method => :delete,
               :class => 'icon icon-del') %>
</div>

削除(destroy アクション)

変更なし

編集(edit アクション)

project_foo_path(@project)project_foo_path(@project, @foo.id) とします(2箇所).
(→ 過去の Redmine では動くのでしょうか?疑問です.)

.\plugins\redmine_standard\app\views\foos\edit.html.erb
<h2><%=h l(:label_foo) %>#<%= @foo.id %></h2>
<%= labelled_form_for :foo, @foo,
                  # :url => project_foo_path(@project),  # No route matches となる
                  :url => project_foo_path(@project, @foo.id),  # 対策
                  :html => {:multipart => true, :id => 'foo-form'} do |f| %>
    <%= render :partial => 'foos/form', :locals => {:form => f} %>
    <%= f.submit l(:button_edit) %>
    <% #= preview_link( preview_project_foo_path(@project), 'foo-form' ) %>
    <% # ↑ No route matches となる. 対策↓ %>
    <%= preview_link( preview_project_foo_path(@project, @foo.id), 'foo-form' ) %>
<% end %>
<div id="preview" class="wiki"></div>

更新(update アクション)

new アクション同様に params[:foo]params[:foo].permit(:subject, :description) とします.

.\plugins\redmine_standard\app\controllers\foos_controller.rb
  def update
    # @foo.attributes = params[:foo]  # プラグイン開発ガイドに記載されているスクリプト
    # ↓のようなエラーが発生する
    # ActiveModel::ForbiddenAttributesError
    @foo.attributes = params[:foo].permit(:subject, :description)  # エラー対策 
    if @foo.save
      flash[:notice] = l(:notice_successful_update)
      redirect_to project_foo_path(@project, @foo.id)
    end
  rescue ActiveRecord::StaleObjectError
    flash.now[:error] = l(:notice_locking_conflict)
  end

プレビュー(preview アクション)

変更なし ※Redmine 4.0 では既に廃止となっている機能です.

レイアウト

変更なし

途中経過④

詳細表示(show アクション)

image.png

編集(edit アクション) & プレビュー(preview アクション)

image.png

削除(destroy アクション)

image.png

Index(index アクション)

image.png

14. まとめ

変更なし

おわりに

今回,チュートリアル(開発ガイド)として内容が充実していると感じた「r-labs | Rails を知らない人のための Redmine プラグイン開発ガイド」を参考にさせていただきました.
このチュートリアルは,対象とするRedmineのバージョンが古いためか(Redmine 2.1〜2.3 を前提),記事の通りに実行してもすんなりとは動作せず,一つ一つ動作を調べながら進めていくこととなりました.
結果として時間はかかってしまいましたが,Ruby, Rails, Redmine について知識を深める良い機会になったと感じています.
参考になりましたら幸いです.

Why do not you register as a user and use Qiita more conveniently?
  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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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