===================
RedmineはRuby on Railsで開発されたプロジェクト管理のアプリケーションです。
主にチケット管理で利用されていますが、プラグインで機能を拡張することができます。
Ruby on Railsの入門としてRedmine Pluginの作り方を紹介します。
(ポイントのキーワードはRailsドキュメントにリンクしています。)
Ruby on Rails
最初にRuby on Railsの特徴を簡単に説明します。
- Webアプリケーションフレームワークです。(言語はもちろんRuby)
- Model - View - Controller (MVC) アーキテクチャを採用しています。
- 設計哲学
- DRY (Don't Repeat Yourself) : 同じことを繰り返さない
- CoC (Convention overConfiguration) : 設定より規約
RoRのMVC
- Model : ビジネスロジックやデータの操作
- View : 出力インターフェイスのデザイン
- Controller : リクエストとレスポンスの制御
Redmine Install
さっそくWebアプリケーション(Redmine)を動かしてみましょう。
Download
プラグインの開発はステーブルのブランチを使いましょう。
$ git clone git://github.com/redmine/redmine.git
$ cd ./redmine/
$ git branch -r
$ git checkout 2.3-stable
Configure
Configはdevelopment
やproduction
など環境でデータベースの接続先を変更することができます。
$ cat << __EOS__ > ./config/database.yml
development:
adapter: sqlite3
database: db/development.sqlite3
__EOS__
Bundler
Gemfileで依存するライブラリが定義されています。bundlerでインストールします。
(bundlerはGemのパッケージングにも利用されます。)
$ bundle install --path=.bundle --without test production mysql postgresql rmagick
Rake
Rakeはmakeに似たビルドツールです。rake db:migrate
コマンドでデータベースにテーブルが作成されます。
$ bundle exec rake generate_secret_token
$ bundle exec rake db:migrate
$ bundle exec rake redmine:load_default_data REDMINE_LANG=en
コマンドの一覧はこちらで確認できます。
$ bundle exec rake -T
Run
rails serverコマンドでWebアプリケーションを起動します。
(RailsはWEBrickというHTTPサーバが標準で提供されています。)
http://localhost:3000/
にアクセスするとRedmineのHome
が表示されます。
$ bundle exec rails server
- デフォルト管理アカウント
- username:admin
- password:admin
Generate Scaffold
Redmine Pluginを作る前にRailsのファイル構造を説明します。
rails generate scaffoldコマンドでファイルを自動作成します。
Scaffold
Webアプリケーションに必要なファイルが作成されます。
(ResourceごとにModel、View、Controllerのセットがあります。)
$ bundle exec rails generate scaffold cat name:string age:integer
...
invoke active_record
create app/models/cat.rb
invoke resource_route
route resources :cats
invoke scaffold_controller
create app/controllers/cats_controller.rb
invoke erb
create app/views/cats/index.html.erb
...
Tree
ファイル構造は厳密に定義されています。
.
│ config.ru
│ Gemfile
│ Rakefile
│ README
│
├─app
│ ├─assets
│ │ ├─javascripts [ジャバスクリプト]
│ │ │ cats.js
│ │ │
│ │ └─stylesheets [スタイルシート]
│ │ cats.css
│ │ scaffold.css
│ │
│ ├─controllers [コントローラクラス]
│ │ account_controller.rb
│ │ cats_controller.rb
│ │
│ ├─helpers [ビューヘルパー]
│ │ application_helper.rb
│ │ cats_helper.rb
│ │
│ ├─models [モデルクラス]
│ │ cat.rb
│ │
│ └─views [ビュースクリプト]
│ ├─cats
│ │ edit.html.erb [編集(ビュー)]
│ │ index.html.erb [表示(リスト)]
│ │ new.html.erb [追加(ビュー)]
│ │ show.html.erb [表示(1件)]
│ │ _form.html.erb
│ │
│ └─layouts [レイアウト]
│
├─config [設定情報]
│ │ database.yml [データベース]
│ │ routes.rb [ルーティング]
│ │
│ └─locales [言語]
│ en.yml
│ ja.yml
│
├─db [データベース]
│ │ development.sqlite3 [データベース本体]
│ │ schema.rb [データベース]
│ │
│ └─migrate
│
├─doc [ドキュメント]
├─lib [ライブラリ]
├─log [ログの出力先]
├─public [公開フォルダ]
├─script [ジェネレータースクリプトなど]
├─test [テストスクリプトなど]
└─tmp [テンポラリファイル]
Run
rake db:migrate
コマンドでcats
テーブルが作成されます。
http://localhost:3000/cats
にアクセスするとListing cats
が表示されます。
$ bundle exec rake db:migrate
$ bundle exec rails server
Migration
データベースのテーブルを管理する仕組みにマイグレーションを採用しています。
さきほどのScaffoldでcats
テーブルを作成するマイグレーションファイルが作成されています。
class CreateCats < ActiveRecord::Migration
def change
create_table :cats do |t|
t.string :name
t.integer :age
t.timestamps
end
end
end
rake db:migrate
コマンドでマイグレーションファイルが処理されます。
(データベースはSQLite3以外にもMySQLやPostgreSQLなど利用できます。 )
$ sqlite3 ./db/development.sqlite3
sqlite> .schema cats
CREATE TABLE "cats" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"name" varchar(255),
"age" integer,
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL);
データベースの構成はschema.rb
ファイルに定義されます。
(O/Rマッピングでデータを操作するので、データベースの種類やSQLなどは意識しません。)
create_table "cats", :force => true do |t|
t.string "name"
t.integer "age"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
Generate Redmine Plugin
Redmine PluginにもGenerateがあります。試しにRedmine Animalプラグインを作成します。
Scaffold
Controllerを作成するとViewも作成されます。
$ bundle exec rails generate redmine_plugin redmine_animal
$ bundle exec rails generate redmine_plugin_controller redmine_animal animal_cats index show
$ bundle exec rails generate redmine_plugin_model redmine_animal animal_cat name:string age:integer
Tree
rails generate scaffold
コマンドで作成されたファイル構造とほぼ同じです。
(規約を覚えると誰でも簡単にコードを読むことができるのはポイントです。)
.
│ init.rb [初期化ファイル]
│ README.rdoc
│
├─app
│ ├─controllers [コントローラクラス]
│ │ animal_cats_controller.rb
│ │
│ ├─helpers [ビューヘルパー]
│ │ animal_cats_helper.rb
│ │
│ ├─models [モデルクラス]
│ │ animal_cat.rb
│ │
│ └─views[ビュースクリプト]
│ └─animal_cats
│ index.html.erb
│ show.html.erb
│
├─assets
│ ├─images
│ ├─javascripts [ジャバスクリプト]
│ └─stylesheets [スタールシート]
├─config
│ │ routes.rb [ルーティング]
│ │
│ └─locales [言語]
│ en.yml
│
├─db
│ └─migrate
│ 001_create_animal_cats.rb
│
├─lib [ライブラリ]
└─test [テストスクリプトなど]
Routing
ルーティングを設定します。routes.rbファイルに設定します。
URLにコントローラとアクション(コントローラのメソッド)を指定します。
resources :cats
だとURLは/cats
でコントローラはcats_controller.rb
ファイルです。
(アクションはCRUDの操作に対応しています。また、RESTfulなURLを提供しています。)
HTTP Verb | Path | action | used for |
---|---|---|---|
GET | /cats | index | 表示(リスト) |
GET | /cats/new | new | 追加(ビュー) |
POST | /cats | create | 作成 |
GET | /cats/:id | show | 表示(1件) |
GET | /cats/:id/edit | edit | 編集(ビュー) |
PUT | /cats/:id | update | 更新 |
DELETE | /cats/:id | destroy | 削除 |
このルートは/animal/cats/
のURLで一覧が表示されます。
$ cat << __EOS__ > ./plugins/redmine_animal/config/routes.rb
RedmineApp::Application.routes.draw do
scope '/animal', as: :animal do
resources :cats, controller: :animal_cats
end
end
__EOS__
ルートの一覧はこちらで確認できます。
$ bundle exec rake routes
Run
rake redmine:plugins:migrate
コマンドでanimal_cats
テーブルが作成されます。
http://localhost:3000/animal/cats
にアクセスするとAnimalCatsController
が表示されます。
$ bundle exec rake redmine:plugins:migrate
$ bundle exec rails server
Adjust
Scaffoldのcat
で作成したファイルをsed
コマンドなどでコピーします。
今回はcat
をanimal_cat
に置換えるだけで動作します。規約通りです。(キリッ
コントローラをコピーします。
$ sed 's/Cat/AnimalCat/g' ./app/controllers/cats_controller.rb > ./plugins/redmine_animal/app/controllers/animal_cats_controller.rb
$ cd ./plugins/redmine_animal/app/controllers
$ cat animal_cats_controller.rb |(rm animal_cats_controller.rb ;sed 's/:cat/:animal_cat/g' > animal_cats_controller.rb)
$ cat animal_cats_controller.rb |(rm animal_cats_controller.rb ;sed 's/cats_url/animal_cats_url/g' > animal_cats_controller.rb)
ビューをコピーします。
$ sed 's/cat_path/animal_cat_path/g' ./app/views/cats/index.html.erb > ./plugins/redmine_animal/app/views/animal_cats/index.html.erb
$ sed 's/cat_path/animal_cat_path/g' ./app/views/cats/show.html.erb > ./plugins/redmine_animal/app/views/animal_cats/show.html.erb
$ sed 's/cats_path/animal_cats_path/g' ./app/views/cats/new.html.erb > ./plugins/redmine_animal/app/views/animal_cats/new.html.erb
$ sed 's/cats_path/animal_cats_path/g' ./app/views/cats/edit.html.erb > ./plugins/redmine_animal/app/views/animal_cats/edit.html.erb
$ cp ./app/views/cats/_form.html.erb ./plugins/redmine_animal/app/views/animal_cats/
Locale
国際化対応で日本語は/config/locales/ja.yml
ファイルに追加します。
$ cat << __EOS__ > ./plugins/redmine_animal/config/locales/ja.yml
ja:
field_age: "年齢"
__EOS__
Redmine Menu
最後にRedmineにメニューを表示します。(今回はアプリケーションメニューにしました。)
$ cat << __EOS__ > ./plugins/redmine_animal/init.rb
Redmine::Plugin.register :redmine_animal do
name 'Redmine Animal 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'
menu :application_menu, :animal, {controller: :animal_cats, action: :index}
end
__EOS__
メニューのAnimal
をクリックするとListing cats
が表示されます。
Redmineは認証・認可の仕組みが標準で実装されているので、業務アプリケーションも簡単に作れます。
次回はScaffoldで出力されたファイルを修正しながらModel - View - Controller (MVC)を紹介します。
Tips
RailsはHTML以外のXML、JSON、CSVなどをレスポンス処理で対応しています。
例えば、URLの末に.json
を付けるとJSON形式で出力されます。
$ curl http://localhost:3000/animal/cats.json
[{"animal_cat":{"age":2,"id":1,"name":"もも"}},{"animal_cat":{"age":0,"id":2,"name":"クロ"}}]