Redmineプラグイン開発¶
プラグイン開発の流れ¶
まず、自由にいじれる独自のRedmine実行環境を用意します。
Linuxマシンの自分のユーザーのHOMEディレクトリ下にRedmineを展開し、Railsに付属するWEBRickサーバー(Redmine 4(Rails 5)からはPumaサーバー)で実行し、DBにはSQLiteを使うのが開発用にはお手軽です。
RedmineとRubyとRailsのバージョン¶
Redmineバージョン | Railsバージョン | Rubyバージョン |
---|---|---|
4.1 | 5.2 | 2.3~2.6 |
4.0 | 5.2 | 2.2.2~2.5 |
3.4 | 4.2 | 1.9.3~2.4 |
rubyのメンテナンス状況¶
2019年12月8日時点の情報
Rubyバージョン | リリース日 | メンテナンス状況 | サポート終了日 |
---|---|---|---|
2.7 | 2019年12月25日(予定) | 未 | 未定 |
2.6 | 2018年12月25日 | 通常メンテナンス | 未定 |
2.5 | 2017年12月25日 | 通常メンテナンス | 未定 |
2.4 | 2016年12月25日 | セキュリティメンテナンス | 2020年3月31日(予定) |
2.3 | 2015年12月25日 | 終了 | 2019年3月31日 |
2.2 | 2014年12月25日 | 終了 | 2018年3月31日 |
2.1 | 2013年12月25日 | 終了 | 2017年3月31日 |
2.0 | 2013年2月24日 | 終了 | 2016年2月24日 |
1.9.3 | 2011年10月31日 | 終了 | 2015年2月23日 |
- 通常メンテナンス
バグ修正やリリースに伴う修正は必要な場合はいつでもバックポートされます。また、重大なセキュリティ上の問題が発見された場合、対応した緊急リリースが行われます。 - セキュリティメンテナンス
セキュリティ上の問題を除いて、バグ修正はバックポートされません。重大なセキュリティ上の問題が発見された場合、対応した緊急リリースが行われます。
Redmine開発環境の用意¶
Linuxコマンドライン環境(Windows 10で利用可能なWindows Subsystem for Linuxを含む)で簡単な開発環境を用意します。
プラグインの雛形生成¶
プラグイン名を指定して、以下のコマンドを実行します。
plugins$ bundle exec rails generate redmine_plugin redmine_hello ^^^^^^^^^^^^^ 生成するプラグイン名
プラグインの雛形で生成されるディレクトリ構造¶
redmine_hello/ ├─ app │ ├─ controllers │ ├─ helpers │ ├─ models │ └─ views ├─ assets │ ├─ images │ ├─ javascripts │ └─ stylesheets ├─ config │ └─ locales ├─ db │ └─ migrate ├─ lib │ └─ tasks └─ test ├─ fixtures ├─ functional ├─ integration └─ unit
プラグインの雛形で生成されるファイル¶
redmine_hello/ ├─ README.rdoc ├─ config │ ├─ locales │ │ └─ en.yml │ └─ routes.rb ├─ init.rb └─ test └─ test_helper.rb
helloプラグイン最低限の実装¶
init.rbの編集¶
プラグイン情報を記載します。記載内容が、Redmineの[管理] > [プラグイン]で確認できればOKです。
雛形で生成された内容 | 雛形を修正した内容(例) |
---|---|
Redmine::Plugin.register :redmine_hello do name 'Redmine Hello 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::Plugin.register :redmine_hello do name 'Redmine Hello plugin' author 'TAKAHASHI,Toru' description 'This is a tiny sample plugin for Redmine' version '0.0.1' url 'http://www.torutk.com/projects/swe/wiki/Redmineプラグイン開発/' author_url 'http://www.torutk.com' end |
プラグイン作成のいろいろな方法¶
Redmineのプラグインには、いくつかの方法があります。現時点で認識しているプラグイン作成方法でも次のものがあります。
- MVCの各部品を作成するMVCプラグイン
- 既存の表示に追加するView hooksプラグイン
- 既存の表示(ビューテンプレート)を差し替えるプラグイン
- 既存の振る舞い(メソッド)を差し替えるパッチプラグイン
- マクロを提供するプラグイン
使い分けに関しては、データをデータベースに保存する場合はモデルの定義が必要なのでMVCプラグイン、既存の表示に付けたしをする程度であれば、適するフック箇所があればView hooksプラグイン、なければビューテンプレートを差し替えるプラグインかパッチプラグイン、Wikiの記載でちょっとした処理をするならマクロといったところでしょうか。
フック¶
Redmineには、プラグインで処理を差し込めるようにあらかじめフックが設けられています。
フックには、View、Controller、Model、HelperとそれぞれRailsの構成要素の種類に応じて用意されています。
フック一覧を調べる¶
Redmine本家サイトに掲載されています。
http://www.redmine.org/projects/redmine/wiki/Hooks_List
次の方法でも調べることができます(上述ページに記載の方法)。
redmine$ grep -r call_hook *
Viewフックのお試し¶
チケット一覧のViewに用意されている:view_issues_index_bottom
にフックを差し込むサンプルを記述します。
フックの定義は上述の方法で調べました。
redmine$ grep -r call_hook * : app/views/issues/index.html.erb:<%= call_hook(:view_issues_index_bottom, { :issues => @issues, :project => @project, :query => @query }) %>
フックを実装するRubyのクラスを定義します。
- redmine/plugins/redmine_mein/lib/redmine_mein/hooks.rb
module RedmineMein class Hooks < Redmine::Hook::ViewListener # 実装 end end
名前の衝突を避けるため、クラス名にプラグイン名を付けて長くなるのは避けたいので、moduleを使って名前空間を導入します。
ただし、moduleを使うとソースファイルを置く場所がモジュール名に対応するディレクトリの下にする必要があるようです。
モジュール名、クラス名は、Pascalケース(先頭が大文字で、続く単語の先頭が大文字のキャメルケース)で記述しますが、ディレクトリ名、ファイル名はスネークケースになるようです。
次に、このフックをプラグインで有効にするため、init.rbに依存を定義します。
require_dependency 'redmine_mein/hooks'
モジュールを導入しているのでモジュール名に対応するディレクトリとクラス名に対応するファイル名(拡張子.rbは不要)を記述します。
コントローラーとビュー¶
RailsのMVC構造におけるVCの部分を作成します。モデルは既存のものを利用します。
プラグインとしては、既にあるデータを活用して、新たなビューを作りたいときに該当します。
コントローラーの雛形作成¶
書式: ruby bin/rails generate redmine_plugin_controller <プラグイン名> <コントローラー名> <アクション>...
redmine$ ruby bin/rails generate redmine_plugin_controller redmine_mein mein index create plugins/redmine_mein/app/controllers/mein_controller.rb create plugins/redmine_mein/app/helpers/mein_helper.rb create plugins/redmine_mein/test/functional/mein_controller_test.rb create plugins/redmine_mein/app/views/mein/index.html.erb
コントローラーには雛形生成時に指定したindexアクションに対応するindexメソッドが定義されます。
ビューには雛形生成時に指定したindexアクションに対応するindex.html.erbファイルが生成されます。
コントローラー名の指定について¶
IDで複数のモデル・インスタンスから1つを識別して制御するコントローラーについては、モデル名の複数形にControllerを付加した命名とします。
IDを指定する必要がないモデル・インスタンスを制御するコントローラーについては、モデル名(単数形)にControllerを付加した命名とします。
例えば、ログインユーザーに1つのインスタンスが紐付くモデルが該当します。
その他、モデルと対応しないコントローラー名は役割に応じた命名とします(複数形でなくてよい)。
- 例1)モデルUserに対応するコントローラー名は、
UsersController
とする。- railsのgenerateコマンドではキャメルケースで指定した場合(この例では
Users
)、スネークケースのファイル名に変換されるはず(users_controller.rb
)ですが、redmine_plugin_controllerを指定した場合、モデル名をキャメルケースで指定すると(Users
)そのままファイル名に使用されてしまいます(Users_controller.rb
)。小文字スネークケースで指定してください。
https://www.redmine.org/issues/28668 - redmine_plugin_modelを指定してモデルを作成する場合は大文字キャメルケースで指定したらファイル名は小文字スネークケースになります。
- railsのgenerateコマンドではキャメルケースで指定した場合(この例では
ルーティング設定¶
プラグインディレクトリ下のconfig/routes.rb にパスを定義します。
IDを指定するモデルのコントローラーについては、resources
でルーティング設定をするのが望ましいです。
Rails.application.routes.draw do
resources :mein
end
resources で指定したコントローラーは、URLのパスにコントローラー名でアクセスが可能となります。
この例では、http://<サーバー名>/mein でindexメソッドに処理が渡されます。
resources :mein
の指定で、次のHTTPリクエストに対するコントローラーのメソッド呼び出しの対応が定義されます。
リクエストメソッド | リクエストURI | コントローラー | メソッド |
---|---|---|---|
GET | /mein | mein | index |
POST | /mein | create | |
GET | /mein/new | new | |
GET | /mein/:id/edit | edit | |
GET | /mein/:id | show | |
PATCH, PUT | /mein/:id | update | |
DELETE | /mein/:id | destroy |
IDを指定する必要のないモデルのコントローラーについては、resource
でルーティング設定をするのが望ましいです。
Rails.application.routes.draw do
resource :besitz
end
resource :besitz
の指定で、次のHTTPリクエストに対するコントローラーのメソッド呼び出しの対応が定義されます。
リクエストメソッド | リクエストURI | コントローラー | メソッド |
---|---|---|---|
GET | /mein | mein | index |
POST | /mein | create | |
GET | /mein/new | new | |
GET | /mein/:id/edit | edit | |
GET | /mein/:id | show | |
PATCH, PUT | /mein/:id | update | |
DELETE | /mein/:id | destroy |
ルーティング設定の確認方法¶
ルーティング設定を確認するのは、次のコマンドで可能です。
redmine$ bundle exec rails routes
indexアクションだけをルート定義する¶
resources :mein, only: :index
プロジェクトの下でコントローラーにアクセスする¶
T.B.D.
部分テンプレート(パーシャル)¶
HTMLテンプレートのある部分に別なファイルで記述した内容を差し込みます。
<%= render partial: 'show_mein' %>
renderメソッドでpartialオプションを指定し、名前を指定します。すると、_名前.html.erb ファイルがその箇所に挿入されます。この例の場合は、_show_mein.html.erb
ファイルが差し込まれます。
なお、他にオプション指定がない場合、partialキーの指定を省略し、<%= render 'show_mein' %>
と記述することができます。
データを部分テンプレートへ渡す¶
部分テンプレートにデータを渡すには、objectオプション、collectionオプション、localsオプションの3種類があります。
- objectオプション
<%= render partial: 'show_mein', object: @mein %>
partialオプションで指定した名前(show_mein)で参照される変数をobjectオプションで渡します。この例では、meinインスタンス変数が_show_mein.html.erb内では、@show_mein
の名前で参照できます。(なんかとてもややこしい)- objectオプションの省略形
<%= render @mein %>
と記述すると、_mein.html.erbが部分テンプレートのファイル名となり、部分テンプレートファイル内では@meinインスタンス変数がmeinという名前のローカル変数として参照できます。
- objectオプションの省略形
- collectionオプション
<%= render partial: 'show_mein', collection: @users %>
collectionオプションでコレクションを指定すると、コレクションの要素ごとに部分テンプレートが展開され、部分テンプレート内では@usersインスタンス変数のコレクションの1つの要素がuserという名前のローカル変数として参照できます。- collectionオプションの省略形
<%= render @users %>
と記述すると、_user.html.erbが部分テンプレートのファイル名となり、部分テンプレートファイル内では@usersインスタンス変数(コレクション)の1つの要素がuserという名前のローカル変数で参照できます。
- collectionオプションの省略形
- localsオプション
<%= render partial: 'show_mein', locals: {mein: @mein, dein: euer[0]} %>
localsオプションでハッシュを渡すと、部分テンプレートファイル内では、ハッシュ内のキーをローカル変数名として、その値で指定された変数を参照することができます。- localsオプションの省略形
<%= render 'show_mein', {mein: @mein, dein: euer[0]} %>
partialオプションとlocalsオプションのオプション名が省略可能です。ただし、partialオプション名を指定した場合は、localsオプション名も指定する必要があります(逆もまた然り)。
- localsオプションの省略形
フォーム¶
ユーザーからの入力を受け付け、サーバーに入力内容を渡すビューです。いくつかの入力項目とサブミットボタンから構成されます。
Ruby on Railsでは、従来からのform_for
およびform_tag
、そしてRuby on Rails 5.1からこの両者を統合するform_with
が提供されています。また、Redmineではさらにform_for
をラップして便利にしたlabelled_form_for
が提供されています。
フォーム種類 | 内容 |
---|---|
form_for |
モデルインスタンスを使用 |
form_tag |
カスタムURLの実現 |
form_with |
form_for とform_tag を統合 |
labelled_form_for |
form_for をラップしたRedmineのAPI |
Ruby on Rails 5.0までは、使い分けは次のとおりです。
- モデルインスタンスがあり、その属性を入力・編集する場合は
labelled_form_for
(中でform_for
を呼び出し)を使います。 - モデルインスタンスとは関係なくURLを指定する場合は
form_tag
を使います。
Ruby on Rails 5.1からは、form_with
が推奨です。form_for
とform_tag
は非推奨(今後のバージョンで廃止)となっています。
form_withの使用例¶
- モデルインスタンスがあり、その属性を入力・編集する例
form_with(model: @post) do |form| form.text_field :title form.text_area :description from.submit end
model:指定だけで内部ではスコープをpostに、URLをurl_for(@post)に生成します。
- モデルインスタンスを使用しない場合の例
form_with(url: different_path, class: 'something', id: 'specific') do |form| form.text_filed :title, 'This is the value of title' form.text_area :description : form.sbumit end
モデル¶
モデルクラスは、データベースのテーブル構造に対応します。モデルクラスのオブジェクト1つは、テーブルのレコードのデータを保持します。そして、モデルクラスのオブジェクトが持つデータをテーブルに反映(新規のレコードとなるならインサート、既存のレコードの変更であればアップデート)します。また、逆にレコードのデータを持つモデルクラスのオブジェクトを取得します。
モデルクラスの生成¶
rails generateコマンドで、redmine_plugin_model を指定し、生成対象プラグインとモデルクラス名を指定します。
今回は属性(データベースのテーブルの列)を指定せず空のモデルを生成します(後から追加は可能です)。
redmine$ bundle exec rails generate redmine_plugin_model redmine_hello Hello create plugins/redmine_hello/app/models/hello.rb create plugins/redmine_hello/test/unit/hello_test.rb create plugins/redmine_hello/db/migrate/001_create_hellos.rb
生成されたファイルの内容は次の通りです(Redmine 4.0/Rails 5.1で生成)。
- hello.rb
class Hello < ActiveRecord::Base end
- 001_create_hellos.rb
class CreateHellos < ActiveRecord::Migration[5.1] def change create_table :hellos do |t| end end end
- マイグレーションのクラス CreateHellos は、ActiveRecord::Migration[5.1]を継承するとちょっと奇妙なコードになっています。Rails 5からは、MigrationはRailsのバージョンによって異なるクラスを継承できるように、Migrationクラスの[]メソッドを呼び引数のバージョンによって対応するクラスを返すようになっています。
従来のように、ActiveRecord::Migration と記述したら次のエラーとなってしまいます。StandardError: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:
- このマイグレーションを実行すると、SQLite3を使用した場合次のテーブルが作成されます。
CREATE TABLE IF NOT EXISTS "hellos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL);
モデルクラスで指定しなくても、主キーで自動インクリメントされるidカラムが用意されます。
- マイグレーションのクラス CreateHellos は、ActiveRecord::Migration[5.1]を継承するとちょっと奇妙なコードになっています。Rails 5からは、MigrationはRailsのバージョンによって異なるクラスを継承できるように、Migrationクラスの[]メソッドを呼び引数のバージョンによって対応するクラスを返すようになっています。
属性の指定¶
モデルを生成するrails generateコマンドで、オプションに属性名と型を指定します。
$ bundle exec rails generate redmine_plugin_model redmine_hello Hello message:string :
属性は、マイグレーション用のコードに記載され、モデルクラスには記述されません。
- hello.rb
class Hello < ActiveRecord::Base end
- db/migrate/002_create_hellos.rb
class CreateHellos < ActiveRecord::Migration[5.1] def change create_table :hellos do |t| t.string :message end end end
- マイグレーションを実行すると、SQLite3を使用した場合次のスキーマが生成されます。
CREATE TABLE IF NOT EXISTS "hellos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "message" varchar);
- マイグレーションを実行すると、SQLite3を使用した場合次のスキーマが生成されます。
属性の型とデータベース上の型¶
モデルの生成時に指定する属性の型と、データベース(MySQL)上のカラムの型の対応は次の通りです。
No | モデルの属性型 | MySQLデータベースの型 | 内容 |
---|---|---|---|
1 | String | varchar(255) | 255文字以下の文字列 |
2 | Text | text | 無制限長の文字列 |
3 | Integer | int(11) | 数値 |
4 | Float | float | |
5 | Decimal | decimal | |
6 | Boolean | tinyint(1) | |
7 | Date | date | |
8 | Time | time | |
9 | DateTime | datetime | |
10 | Timestamp | datetime |
タイムスタンプに関する属性¶
モデルオブジェクト(データベースのテーブルのレコード)の生成日時および更新日時は、マイグレーション用のコードにtimestampsの指定をすると生成されます。- db/migrate/001_create_hellos.rb
class CreateHellos < ActiveRecord::Migration[5.1] def change create_table :hellos do |t| t.string :message t.timestamps end end end
- SQLite3の場合次のスキーマが生成されます。
CREATE TABLE IF NOT EXISTS "hellos" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "message" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
Railsでは、モデルのレコードを新規生成時に、created_atまたはcreated_onカラムが存在しnilであれば作成日時を自動挿入し、updated_atまたはupdated_onカラムが存在しnilであれば同じく作成日時を自動挿入します。
モデルのレコードの更新時は、updated_atまたはupdated_onカラムが存在すれば更新日時を自動挿入します。
マイグレーションスクリプトあれこれ¶
- changeメソッドで記述するのは、add_column等それだけでマイグレーションの実行とそのロールバックが可能な場合
- upメソッドとdownメソッドの双方を記述するのは、changeメソッドだけではロールバックができない場合
マイグレーションスクリプトのファイル命名¶
- カラムの追加
add_<カラム名>_to_<テーブル名>.rb
- カラムの削除
remove_<カラム名>_from_<テーブル名>.rb
- テーブルの作成
create_<テーブル名>.rb
- テーブル名の変更
rename_hotels_to_indias.rb
マイグレーションのロールバック¶
マイグレーションスクリプトに誤りがあった場合など、マイグレーションを元に戻したい場合は次のコマンドを実行します。
bundle exec rails redmine:plugins:migrate NAME=<プラグイン名> VERSION=<戻したいバージョン番号>
<プラグイン名>は、ロールバック対象プラグインの名前を指定します。
<戻したいバージョン番号>は、プラグインディレクトリのdb/migrate/下にある各マイグレーションスクリプトのうち、ロールバックによりどこまで適用したこととするかをマイグレーションスクリプトのファイル名の先頭番号で指定します。
例えば、003_add_foo_to_bar.rb までを適用し、004_add_a_to_bar.rb をロールバックする場合は、<戻したいバージョン番号>に3を指定します。
モデルオブジェクトのメソッド¶
- インスタンスを生成 new
- インスタンスの属性を更新 attributes
引数に属性名をキー、値をバリューとするハッシュを渡して複数属性をまとめて設定 - インスタンスの属性をデータベースに保存 save
- インスタンスの生成とデータベース保存 create
引数は属性名をキー、値をバリューとするハッシュを渡し、インスタンスの生成とデータベース保存を一気に実行 - インスタンスの属性を更新しデータベース保存 update
- インスタンスの属性を1つ更新しデータベース保存 update_attribute
- すべてのインスタンスを取得 all
- 主キーで検索 find
引数には検索するキーを複数指定可。見つからないとActiveRecord::RecordNotFound例外発行。 - 条件を指定し1件を検索 find_by
LIMITで1個に絞っている模様。見つからないとnilを返す。 - 条件を指定しN件を検索 where
- 件数を調べる count
- 並び順を指定 order
whereの指定方法¶
- 文字列指定
モデル.where("category_id = '3'")
- ハッシュ指定
モデル.where(category_id: 3)
モデル間の関係¶
モデル同士の関連の種類(抜粋)
- belongs_to
- has_one
- has_many
belongs_to¶
class Alfa < ActiveRecord::Base
end
class Bravo < ActiveRecord::Base
belongs_to :alfa
- bravo.alfa と属性としてアクセス可能
- bravosテーブルが alfa_idを外部キーとしてalfasテーブルを参照
class Charlie < ActiveRecord::Base
belongs_to :author, class_name: 'User'
関連するクラス名(テーブル名)とは別の名前で関連付けする場合、class_nameで実のクラス名を指定します。
外部キーは、この場合、author_id の列名で生成されます。
has_many¶
belongs_to で関連付けられた側に指定します。belongs_toと対で使用しないと意味がなさそうです。一方、belongs_toを単独して使用することは意味があります。
class Alfa < ActiveRecord::Base
has_many :bravos
end
class Bravo < ActiveRecord::Base
belongs_to :alfa
- alfa.bravos と属性としてアクセス可能(配列として取得)
alfa.bravos.each do |b|
マクロ¶
マクロは、Wikiに埋め込むと実行時に展開されるブロックです。
テスト¶
プラグインのテストを記述および実行するにあたり、テスティングフレームワークが利用可能です。よく用いられているのは、Rails(Ruby)標準搭載のMinitestフレームワークと、外部ライブラリのRSpecです。
Minitestは、テストデータをfixtureと呼ぶYAML等のファイル形式で記述し、テストコードをRubyで記述し、テストを実行します。テストはassertで成否を判定しテスト実行結果として失敗したassertの件数が表示されます。テストの粒度はユニット、ファンクショナル、インテグレーションの3段階あります。
RSpecは、テストデータをFactoryBotライブラリを使って記述し、テストコードをRubyの内部DSLで記述し、テストを実行します。テストはmatcherを使って成否を判定します。テストの粒度はモデルに対するテスト、コントローラーに対するテスト、ヘルパーのテストがあります。
この他、エンドツーエンドテストでは外部ライブラリのCapybaraを用いるのが最近の流れです。Capybaraは、Seleniumを使ったテストを自動化するものです。
Minitestによるテスト¶
fixtureファイルの置き場所とテストでの利用方法¶
Minitestによるテストでは、デフォルトではRedmineインストールディレクトリ/test/fixtures/にあるfixtureファイルを使用します。プラグイン独自のfixtureファイルを使う場合は、テスト実行前にプラグイン独自のfixtureファイルをRedmineインストールディレクトリ/test/fixtures/へコピーします。ただし、これは手間がかかるのと、バージョン管理ツール上で作業ディレクトリのRedmineインストールディレクトリ/test/fixturesに変更が発生したと検知されてしまうのでちょっと面倒です。そこで、プラグインのtest_helper.rbに、プラグイン独自のディレクトリにあるfixtureファイルを読み込むコードを追加します。
- プラグインディレクトリ/test/test_helper.rb
# -*- coding: utf-8 -*- # Load the normal Rails helper require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper') module Redmine module PluginFixturesLoader def self.included(base) base.class_eval do def self.plugin_fixtures(*symbols) ActiveRecord::FixtureSet.create_fixtures(File.dirname(__FILE__) + '/fixtures/', symbols) end end end end end ## ファンクショナルテスト unless ActionController::TestCase.included_modules.include?(Redmine::PluginFixturesLoader) ActionController::TestCase.send :include, Redmine::PluginFixturesLoader end ## ユニットテスト unless ActiveSupport::TestCase.included_modules.include?(Redmine::PluginFixturesLoader) ActiveSupport::TestCase.send :include, Redmine::PluginFixturesLoader end ## インテグレーションテスト unless Redmine::IntegrationTest.included_modules.include?(Redmine::PluginFixturesLoader) Redmine::IntegrationTest.send :include, Redmine::PluginFixturesLoader end
テストコードからfixtureの読み込み使用する例を次に示します。
- プラグインディレクトリ/test/units/term_category_test.rb
require File.dirname(__FILE__) + '/../test_helper' class TermCategoryTest < ActiveSupport::TestCase plugin_fixtures :term_categories def test_load_fixture_one cat1 = TermCategory.find(1) assert_same 1, cat1.id end end
このコードでは、plugin_fixtures :term_categories
と記述することで、プラグインディレクトリ/test/fixtures/term_categories.yml をテストデータとして読み込みます。読み込んだテストデータはモデルクラスのメソッドを通じて取得します。
Redmineインストールディレクトリ/test/fixtures/にあるfixtureファイルを読み込むときはテストコード側にはfixtures :users
のように記述します。fixturesメソッドで参照するときは、users(:user_a)
のようにしてfixtureファイルに名前user_a
として定義したデータを取得できます。plugin_fixtures
で指定した場合は後者の呼び方はできません。プラグイン独自のfixtureファイルでfixtureの名前でデータを取得したいときは、次のように指定します。
plugin_fixtures :term_categories
fixtures :term_categories
:
def test_some
cat_one = term_categories(:one)
モデルのテスト(unit test)¶
モデルのテストで実施すべき項目は次となります。
- validationのテスト
- データベースの制約(整合性)テスト
- publicなメソッドのテスト
コントローラーのテスト(functional test)¶
コントローラーのテストで実施すべき項目は次となります。
- アクションのテスト
統合テスト(integrated test)¶
システムテスト(end to end test)¶
便利集¶
Railsコンソール¶
Rails環境をコンソールで扱います。
redmine$ bundle exec rails console irb(main):002:0> "man".pluralize => "men" irb(main):003:0>
参考資料¶
RAILS GUIDES日本語訳¶
- Active Recordの関連付け(アソシエーション)
- Railsのルーティング
- Active Record マイグレーション
- Ruby on Rails 5.0リリースノート
- Rails 4.2からRails 5.0へのアップグレード
- Ruby on Rails 5.1リリースノート
- Ruby on Rails 5.2リリースノート
Rails 4から5へのアップグレード対応¶