Project

General

Profile

Actions

まとめ

プラグインの作り方のまとめです。

Rails

Rails のポイントは MVC 構造と 2 つの方針です。

MVC 構造

Model データを扱う部分。クラスのインスタンスがデータベースの 1 つのレコードに対応し、テーブルからの取得にはクラスメソッドを使用する
View html を作成する部分。 Erb で埋め込み式の ruby コードを評価して作成する
Control ユーザのアクションに応答する部分。アクションに対応したメソッドを実行する

設定よりも規約

名前に規則を持たせることで設定の手間を省き、簡単に作成できるようにします。

ファイルを置くディレクトリは決まっています。

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

(Redmine のトップディレクトリ)/plugins/(プラグイン名)

プラグインディレクトリ内

init.rb            最初にロードされるファイル。プラグインの定義を記述
app/
├ controllers/         コントローラ
├ models/              モデル
└ views/               ビュー
db/migrate/             データベース操作
config/locales/         国際化用メッセージファイルの格納

ファイルは基本的に 1 ファイルに 1 クラスを記述し、ファイル名はクラス名をスネークケースに変換した名前になります。

FoosController -> foos_controller.rb

ビューのファイルは 1 ファイルに 1 つのアクション用ページを記述します。

app/views/(コントローラ名)/(アクション名).html.erb

ex.) app/views/foos/index.html.erb

繰り返しの禁止

同じことを何度も書かない。

繰り返しを避けるための機能が用意されています。

before_filter

コントローラで各アクションのメソッドの前に実行されるメソッドを指定します。

部分描画

ビューで同じ部分を別ファイルとして共通化します。
部分描画用のファイル名には先頭に _ を付けます。指定する場合は _ と拡張子を省き、 app/views からのパスを書きます。

<%= render :partial=>"foos/form" %>

レイアウト

全ビューで共通する部分はレイアウトファイルに書きます。
レイアウトファイルは app/views/layouts 以下に置き、コントローラでレイアウトを指定します。

layout "standard" 

スケルトンの生成

プラグインを作るには雛形となるスケルトンを作成して、そこに中身を追加していきます。
スケルトンは プラグイン全体コントロールモデル の 3 つです。 ビューはコントロールと一緒に生成されます。

プラグインの作成は Rails のトップディレクトリで実行します。

$ ruby script/rails redmine_plugin プラグイン名
$ ruby script/rails redmine_plugin_controler プラグイン名 コントローラ名 [アクション名 ...]
$ ruby script/rails redmine_plugin_model プラグイン名 モデル名 [カラム名:型 ...]

モデルの場合にはデータベースへのテーブル作成用のファイルも生成されます。
テーブルの作成には rake を使用します。

$ rake redmine:plugins:migrate

スケルトン生成後、次のような作業を行うことになります。

init.rb

  • バージョンなどの各情報を設定します。
  • プラグインのトップページを呼び出すためのメニューを追加します。

モデル

  • データ要素が妥当なものかの判定処理を追加します。

コントロール

  • 各アクションごとのメソッドを実装します。

ビュー

  • 各アクションごとのページの内容を記述します。

プロジェクトごとのプラグイン

プロジェクトごとにデータ管理するプラグインにするために必要なことをあげます。

  • init.rb
    • プロジェクトモジュールの登録 project_module
      • 各アクションの権限の指定 permission
    • プロジェクトメニューへの項目の追加 menu
  • コントローラクラス
    • @project の設定 Project.find(params[:id])
    • ログインチェック authorize
    • メニューを選択状態 menu_item

国際化

config/locals 以下に言語別のメッセージファイル(en.yml, ja.yml など)を作成します。
メッセージファイルには、キーとメッセージのペアを記述します。

言語の識別子:
  シンボル名: メッセージ
  シンボル名: メッセージ
          # :

メッセージファイルの記述には注意事項があります。

  • インデントで階層化される
  • タブの使用禁止
  • 文字コードは UTF-8

通常、メッセージを取得する場合には次の国際化ライブラリ(i18n)のメソッドを使用します。

l(:キー)

しかし、以下のものは自動的にキーが検索されます。あえてラベルを変えたい場合はオプションで :label の値を指定します。

項目 検索キー
メニュー項目 label_項目名 label_standard
モジュール名 project_module_モジュール名 project_module_standard
権限項目 permission_名前 permission_view_foos
フォームのフィールド field_フィールド名 field_subject

データの流れ

ビュー → コントロール

メニューやビューの link_to などで作ったリンクまたはフォームからコントロールのアクションが呼び出されます。

リンクはハッシュで指定する場合、 :control, :action などの要素でアドレス(呼び出すアクション)を指定し、後のパラメータは params 変数にハッシュとして格納されてコントロールに渡されます。 プロジェクトの識別名は project_id をキーとして指定します。:id パラメータは特殊でアドレスの一部としても使われます。

link_to 表示文字列, {:control=>:foos, :action=> :show, :project_id => "demo", :id => 1}

このリンクをルーティングで設定したパスで指定すると簡潔で理解しやすくなります。

link_to 表示文字列, project_foo_path("demo", 1)

アドレスのルーティングは下記のように config/routes.rb で URL を設定する必要があります。

Rails.application.routes.draw do
  resources :projects do
    resources :foos do
       post  'preview', :on => :collection
       put   'preview', :on => :member
    end
  end
end

ルーティングは rake routes で確認します。

        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
                     PUT          /projects/:project_id/foos/:id(.:format)          foos#update    
                     DELETE       /projects/:project_id/foos/:id(.:format)          foos#destroy

この場合、アドレスは以下のようになります。

アドレス: http://127.0.0.1/projects/demo/foos/1
params = {:project_id => "demo", :id => "1"}

フォームで送る場合はフォームの各フィールドのパラメータが params[:フォーム名] の子要素のハッシュで格納されて渡されます。

<% form_for :foo, (モデルのオブジェクト), 
            :url=>project_foo_path("demo") do |f| %>
  <p> <%= f.text_field(:subject) %>    </p>
  <p> <%= f.text_area(:description) %> </p>
      <%= f.submit l(:button_create) %>
<% end %>
アドレス: http://127.0.0.1/projects/demo/foos/new
params = {:project_id => "demo", :foo=>{:subject=>(入力値), :description=>(入力値) } }

コントロール ← モデル

データベースからのデータの取得はモデルのクラスメソッドを使ってコントロール内で行います。

Foo.find(:all, :conditions => ["project_id = #{@project.id} "])   # project_id の一致する全要素を取得
Foo.find(:first, :conditions => ["id = #{params[:id]} "])   # id の一致する最初の要素を取得
Foo.find_by_id(params[:id])                                 # 前の簡易版

データベースに変更を加える場合には Foo のオブジェクトのメソッドを使用します。

操作 関数 説明
追加 foo.save id メンバが 0 で保存をすると新しいレコードとして追加されます。追加の際 id が連番で割り振られます。
更新 foo.save id が 0 以外の場合には対象となるレコードが更新されます。
削除 foo.destory テーブルからレコードが削除されます

コントロール → ビュー

ビューの Erb ファイルの評価はコントロール内で行われるので、コントロールクラスのインスタンス変数(@)はビュー内でもそのまま使用できます。

終わりに

以上でプラグインの開発ガイドは終了です。
作成方法の基本はご理解いただけたでしょうか。

実際にプラグインを作ろうと思った場合、ガイドの知識だけでは不足すると思います。そういったときは プラグイン_Tips を見てください。こちらには応用的な機能の実現方法が紹介されています。
そこにも知りたい内容がない場合は、他のプラグインや Redmine 自身のソースを見てください。おそらくソースの中身が大分読みやすくなっているのではないでしょうか。

これから Redmine に不足を感じたら、自分でプラグインを作って満足のいく Redmine に仕上げていってください。
そしてプラグインができたらどんどん公開して、みんなで Redmine をいいソフトにしていきましょう。


^ <<

Updated by NAITOH Jun over 6 years ago · 6 revisions