プロジェクト

全般

プロフィール

GuideConclusion » 履歴 » バージョン 6

NAITOH Jun, 2013/04/14 21:33
RESTfulな実装に変更。

1 1 Mitsuyoshi Yoshida
h1. まとめ
2
3
プラグインの作り方のまとめです。
4
5
h2. Rails 
6
7
Rails のポイントは MVC 構造と 2 つの方針です。
8
9
h3. MVC 構造
10
11
|_. Model | データを扱う部分。クラスのインスタンスがデータベースの 1 つのレコードに対応し、テーブルからの取得にはクラスメソッドを使用する |
12
|_. View | html を作成する部分。 Erb で埋め込み式の ruby コードを評価して作成する |
13
|_. Control | ユーザのアクションに応答する部分。アクションに対応したメソッドを実行する |
14
15
16
17
h3. 設定よりも規約
18
19
名前に規則を持たせることで設定の手間を省き、簡単に作成できるようにします。
20
21
ファイルを置くディレクトリは決まっています。
22
23
24
*プラグインのディレクトリ*
25
26
<pre>
27 5 NAITOH Jun
(Redmine のトップディレクトリ)/plugins/(プラグイン名)
28 1 Mitsuyoshi Yoshida
</pre>
29
30
*プラグインディレクトリ内*
31
32
<pre>
33
init.rb			最初にロードされるファイル。プラグインの定義を記述
34
app/
35
├ controllers/         コントローラ
36
├ models/              モデル
37
└ views/               ビュー
38
db/migrate/             データベース操作
39
config/locales/         国際化用メッセージファイルの格納
40
</pre>
41
42
43
ファイルは基本的に 1 ファイルに 1 クラスを記述し、ファイル名はクラス名をスネークケースに変換した名前になります。
44
45
<pre>
46
FoosController -> foos_controller.rb
47
</pre>
48
49
ビューのファイルは 1 ファイルに 1 つのアクション用ページを記述します。
50
51
<pre>
52
app/views/(コントローラ名)/(アクション名).html.erb
53
54
ex.) app/views/foos/index.html.erb
55
</pre>
56
57
58
59
h3. 繰り返しの禁止
60
61
同じことを何度も書かない。
62
63
繰り返しを避けるための機能が用意されています。
64
65
*before_filter*
66
67
コントローラで各アクションのメソッドの前に実行されるメソッドを指定します。
68
69
*部分描画*
70
71
ビューで同じ部分を別ファイルとして共通化します。
72
部分描画用のファイル名には先頭に _ を付けます。指定する場合は _ と拡張子を省き、 app/views からのパスを書きます。
73
74 6 NAITOH Jun
<pre><code class="erb">
75 1 Mitsuyoshi Yoshida
<%= render :partial=>"foos/form" %>
76
</code></pre>
77
78
79
*レイアウト*
80
81
全ビューで共通する部分はレイアウトファイルに書きます。 
82
レイアウトファイルは app/views/layouts 以下に置き、コントローラでレイアウトを指定します。
83
84
<pre><code class="ruby">
85
layout "standard"
86
</code></pre>
87
88
89
h2. スケルトンの生成
90
91
プラグインを作るには雛形となるスケルトンを作成して、そこに中身を追加していきます。
92
スケルトンは *プラグイン全体* 、 *コントロール* 、 *モデル* の 3 つです。 ビューはコントロールと一緒に生成されます。
93
94
プラグインの作成は Rails のトップディレクトリで実行します。
95
96
<pre>
97 5 NAITOH Jun
$ ruby script/rails redmine_plugin プラグイン名
98
$ ruby script/rails redmine_plugin_controler プラグイン名 コントローラ名 [アクション名 ...]
99
$ ruby script/rails redmine_plugin_model プラグイン名 モデル名 [カラム名:型 ...]
100 1 Mitsuyoshi Yoshida
</pre>
101
102
モデルの場合にはデータベースへのテーブル作成用のファイルも生成されます。
103
テーブルの作成には rake を使用します。
104
105
<pre>
106 5 NAITOH Jun
$ rake redmine:plugins:migrate
107 1 Mitsuyoshi Yoshida
</pre>
108
109
110
スケルトン生成後、次のような作業を行うことになります。
111
112
*init.rb*
113
114
* バージョンなどの各情報を設定します。
115
* プラグインのトップページを呼び出すためのメニューを追加します。
116
117
*モデル*
118
119
* データ要素が妥当なものかの判定処理を追加します。
120
121
*コントロール*
122
123
* 各アクションごとのメソッドを実装します。
124
125
*ビュー*
126
127
* 各アクションごとのページの内容を記述します。
128
129
130
131
h2. プロジェクトごとのプラグイン
132
133
プロジェクトごとにデータ管理するプラグインにするために必要なことをあげます。
134
135
* init.rb
136
** プロジェクトモジュールの登録 project_module 
137
*** 各アクションの権限の指定 permission
138
** プロジェクトメニューへの項目の追加 menu
139
* コントローラクラス
140
** @project の設定 Project.find(params[:id])
141
** ログインチェック authorize
142
** メニューを選択状態 menu_item
143
144
145
h2. 国際化
146
147
config/locals 以下に言語別のメッセージファイル(en.yml, ja.yml など)を作成します。
148
メッセージファイルには、キーとメッセージのペアを記述します。
149
150
<pre><code class="yaml">
151
言語の識別子:
152
  シンボル名: メッセージ
153
  シンボル名: メッセージ
154
          # :
155
</code></pre>
156
157
メッセージファイルの記述には注意事項があります。
158
159
* インデントで階層化される
160
* タブの使用禁止
161
* 文字コードは UTF-8
162
163
164
通常、メッセージを取得する場合には次の国際化ライブラリ(i18n)のメソッドを使用します。
165
166
<pre><code class="ruby">
167
l(:キー)
168
</code></pre>
169
170
171
しかし、以下のものは自動的にキーが検索されます。あえてラベルを変えたい場合はオプションで :label の値を指定します。
172
173
|_. 項目       |_. 検索キー   |_. 例             |
174
| メニュー項目 | label_項目名 | label_standard |
175
| モジュール名 | project_module_モジュール名 | project_module_standard |
176
| 権限項目     | permission_名前 | permission_view_foos |
177
| フォームのフィールド | field_フィールド名 |field_subject |
178
179
180
h2. データの流れ
181
182
h3. ビュー → コントロール
183
184
メニューやビューの link_to などで作ったリンクまたはフォームからコントロールのアクションが呼び出されます。
185
186 6 NAITOH Jun
リンクはハッシュで指定する場合、 :control, :action などの要素でアドレス(呼び出すアクション)を指定し、後のパラメータは *params* 変数にハッシュとして格納されてコントロールに渡されます。 プロジェクトの識別名は project_id をキーとして指定します。:id パラメータは特殊でアドレスの一部としても使われます。
187 1 Mitsuyoshi Yoshida
188
<pre><code class="ruby">
189 6 NAITOH Jun
link_to 表示文字列, {:control=>:foos, :action=> :show, :project_id => "demo", :id => 1}
190 1 Mitsuyoshi Yoshida
</code></pre>
191
192 6 NAITOH Jun
このリンクをルーティングで設定したパスで指定すると簡潔で理解しやすくなります。
193 1 Mitsuyoshi Yoshida
<pre><code class="ruby">
194 6 NAITOH Jun
link_to 表示文字列, project_foo_path("demo", 1)
195
</code></pre>
196
197
アドレスのルーティングは下記のように config/routes.rb で URL を設定する必要があります。
198
<pre><code class="ruby">
199 1 Mitsuyoshi Yoshida
Rails.application.routes.draw do
200 6 NAITOH Jun
  resources :projects do
201
    resources :foos do
202
       post  'preview', :on => :collection
203
       put   'preview', :on => :member
204
    end
205
  end
206 1 Mitsuyoshi Yoshida
end
207
</code></pre>
208
209 6 NAITOH Jun
ルーティングは *rake routes* で確認します。
210
<pre>
211
        project_foos GET          /projects/:project_id/foos(.:format)              foos#index      
212
                     POST         /projects/:project_id/foos(.:format)              foos#create     
213
     new_project_foo GET          /projects/:project_id/foos/new(.:format)          foos#new        
214
    edit_project_foo GET          /projects/:project_id/foos/:id/edit(.:format)     foos#edit       
215
         project_foo GET          /projects/:project_id/foos/:id(.:format)          foos#show
216
                     PUT          /projects/:project_id/foos/:id(.:format)          foos#update    
217
                     DELETE       /projects/:project_id/foos/:id(.:format)          foos#destroy
218
</pre>
219
220 1 Mitsuyoshi Yoshida
この場合、アドレスは以下のようになります。
221
<pre>
222 6 NAITOH Jun
アドレス: http://127.0.0.1/projects/demo/foos/1
223 3 Mitsuyoshi Yoshida
params = {:project_id => "demo", :id => "1"}
224 1 Mitsuyoshi Yoshida
</pre>
225
226
フォームで送る場合はフォームの各フィールドのパラメータが params[:フォーム名] の子要素のハッシュで格納されて渡されます。
227
228
<pre><code class="ruby">
229 6 NAITOH Jun
<% form_for :foo, (モデルのオブジェクト), 
230
            :url=>project_foo_path("demo") do |f| %>
231 1 Mitsuyoshi Yoshida
  <p> <%= f.text_field(:subject) %>    </p>
232
  <p> <%= f.text_area(:description) %> </p>
233
      <%= f.submit l(:button_create) %>
234
<% end %>
235
</code></pre>
236
237 5 NAITOH Jun
<pre>
238 3 Mitsuyoshi Yoshida
アドレス: http://127.0.0.1/projects/demo/foos/new
239 1 Mitsuyoshi Yoshida
params = {:project_id => "demo", :foo=>{:subject=>(入力値), :description=>(入力値) } }
240
</pre>
241
242
243
h3. コントロール ← モデル
244
245
データベースからのデータの取得はモデルのクラスメソッドを使ってコントロール内で行います。
246
247
<pre><code class="ruby">
248 4 Mitsuyoshi Yoshida
Foo.find(:all, :conditions => ["project_id = #{@project.id} "])   # project_id の一致する全要素を取得
249
Foo.find(:first, :conditions => ["id = #{params[:id]} "])   # id の一致する最初の要素を取得
250 1 Mitsuyoshi Yoshida
Foo.find_by_id(params[:id])                                 # 前の簡易版
251
</code></pre>
252
253
データベースに変更を加える場合には Foo のオブジェクトのメソッドを使用します。
254
255
|_. 操作 |_. 関数 |_. 説明 |
256
| 追加  | foo.save | id メンバが 0 で保存をすると新しいレコードとして追加されます。追加の際 id が連番で割り振られます。|
257
| 更新  | foo.save | id が 0 以外の場合には対象となるレコードが更新されます。 |
258
| 削除  | foo.destory | テーブルからレコードが削除されます |
259
260
261
h3. コントロール → ビュー
262
263
ビューの Erb ファイルの評価はコントロール内で行われるので、コントロールクラスのインスタンス変数(@)はビュー内でもそのまま使用できます。
264
265
266
h1. 終わりに
267
268
以上でプラグインの開発ガイドは終了です。
269
作成方法の基本はご理解いただけたでしょうか。
270
271
実際にプラグインを作ろうと思った場合、ガイドの知識だけでは不足すると思います。そういったときは [[プラグイン_Tips]] を見てください。こちらには応用的な機能の実現方法が紹介されています。
272
そこにも知りたい内容がない場合は、他のプラグインや Redmine 自身のソースを見てください。おそらくソースの中身が大分読みやすくなっているのではないでしょうか。
273
274
これから Redmine に不足を感じたら、自分でプラグインを作って満足のいく Redmine に仕上げていってください。
275
そしてプラグインができたらどんどん公開して、みんなで Redmine をいいソフトにしていきましょう。
276
277
278
---
279
280
| [[プラグイン開発ガイド|^]] | [[GuideActionElse|<<]] |