プロジェクト

全般

プロフィール

プラグイン チュートリアル » 履歴 » バージョン 8

Haru Iida, 2009/05/28 16:06

1 1 Haru Iida
www.redmine.orgの"Plugin Turorial":http://www.redmine.org/wiki/redmine/Plugin_Tutorial を和訳してみます。
2
3
h1. プラグイン チュートリアル
4
5 6 Haru Iida
注意: このチュートリアルはRedmineの開発リビジョン @r1786@ 以上を対象にしています。
6 1 Haru Iida
7
{{toc}}
8
9
h2. 新しいプラグインを作る。
10
11
プラグインの新規作成はRedmineのプラグインジェネレータを使用して行うことができます。
12
ジェネレータのコマンドは以下です。:
13
14
<pre>ruby script/generate redmine_plugin <plugin_name></pre>
15
16
コマンドプロンプトを開き "cd" であなたがredmineをインストールしたディレクトリに移動し、以下のコマンドを実行してみましょう。:
17
18
  % ruby script/generate redmine_plugin Polls
19
20 2 Haru Iida
@vendor/plugins/redmine_polls@ の下に以下のようなファイルとディレクトリが作られます:
21 1 Haru Iida
22
<pre>
23
      create  vendor/plugins/redmine_polls/app/controllers
24
      create  vendor/plugins/redmine_polls/app/helpers
25
      create  vendor/plugins/redmine_polls/app/models
26
      create  vendor/plugins/redmine_polls/app/views
27
      create  vendor/plugins/redmine_polls/db/migrate
28
      create  vendor/plugins/redmine_polls/lib/tasks
29
      create  vendor/plugins/redmine_polls/assets/images
30
      create  vendor/plugins/redmine_polls/assets/javascripts
31
      create  vendor/plugins/redmine_polls/assets/stylesheets
32
      create  vendor/plugins/redmine_polls/lang
33
      create  vendor/plugins/redmine_polls/README
34
      create  vendor/plugins/redmine_polls/init.rb
35
      create  vendor/plugins/redmine_polls/lang/en.yml
36
</pre>
37
38 2 Haru Iida
@vendor/plugins/redmine_polls/init.rb@ を編集してあなたのプラグインの情報を書き込んでください。(name, author, description および version):
39 1 Haru Iida
40
<pre><code class="ruby">
41
require 'redmine'
42
43
Redmine::Plugin.register :redmine_polls do
44
  name 'Polls plugin'
45
  author 'John Smith'
46
  description 'A plugin for managing polls'
47
  version '0.0.1'
48
end
49
</code></pre>
50
51 2 Haru Iida
そしてRedmineを起動し、ブラウザから次のアドレスを入力します。http://localhost:3000/admin/info.
52
ログイン後、あなたのプラグインがプラグイン一覧に加わっていることが確認できます。
53 1 Haru Iida
54 4 Haru Iida
!plugins_list1.png!
55 1 Haru Iida
56 5 Haru Iida
h2. モデルを作る
57 1 Haru Iida
58 5 Haru Iida
それではこのプラグインのモデルとして Poll を作ってみましょう。:
59 1 Haru Iida
60
  ruby script/generate redmine_plugin_model polls poll question:string yes:integer no:integer
61
62 5 Haru Iida
このコマンドで Poll モデルおよびPollモデルに対応したマイグレーションファイルが作成されます。
63
(訳注:マイグレーションファイルとは、RedmineのDBにこのモデル用のテーブルを作成するためのスクリプトファイルです)
64 1 Haru Iida
65 5 Haru Iida
ここで注意が必要です。timestamped migrationは今のRedmineプラグインエンジンではサポートされていません。ファイル名についているタイムスタンプを"001", "002"のような名前に変更してください。
66 1 Haru Iida
67 5 Haru Iida
実際にデータベースへのマイグレーションを行うためには以下のコマンドを実行します。:
68 1 Haru Iida
69
  rake db:migrate_plugins
70
71 5 Haru Iida
すべてのプラグインはそれぞれに自身のマイグレーションファイルを持っています。
72 1 Haru Iida
73 6 Haru Iida
それではconsoleスクリプトからPollのデータを追加してみましょう。ちゃんとテーブルが作られていることを確認できます。consoleを使用すると対話的にRedmineを動かして確認できます。また、遊びながらいろいろな情報を得ることができます。それでは2つのPollオブジェクトを作ります。
74 1 Haru Iida
75
<pre>
76
script/console
77
>> Poll.create(:question => "Can you see this poll ?")
78
>> Poll.create(:question => "And can you see this other poll ?")
79
>> exit
80
</pre>
81
82 6 Haru Iida
プラグインディレクトリの @vendor/plugins/redmine_polls/app/models/poll.rb@ を編集して #vote メソッドを追加しましょう。このメソッドはコントローラから実行されるものです。:
83 1 Haru Iida
84
<pre><code class="ruby">
85
class Poll < ActiveRecord::Base
86
  def vote(answer)
87
    increment(answer == 'yes' ? :yes : :no)
88
  end
89
end
90
</code></pre>
91
92 7 Haru Iida
h2. コントローラを作成する。
93 1 Haru Iida
94 7 Haru Iida
この段階ではまだこのプラグインは何もすることができません。このプラグインにコントローラを追加してみましょう。コントローラの作成にはプラグインコントローラジェネレータを使用できます。文法は以下です。:
95 1 Haru Iida
96
<pre>ruby script/generate redmine_plugin_controller <plugin_name> <controller_name> [<actions>]</pre>
97
98 7 Haru Iida
ではコマンドプロンプトから以下のように打ってみましょう。:
99 1 Haru Iida
100
<pre>
101
% ruby script/generate redmine_plugin_controller Polls polls index vote
102
      exists  app/controllers/
103
      exists  app/helpers/
104
      create  app/views/polls
105
      create  test/functional/
106
      create  app/controllers/polls_controller.rb
107
      create  test/functional/polls_controller_test.rb
108
      create  app/helpers/polls_helper.rb
109
      create  app/views/polls/index.html.erb
110
      create  app/views/polls/vote.html.erb
111
</pre>
112
113 7 Haru Iida
コントローラ @PollsController@ と2つのアクション (@#index@ and @#vote@) が作成されます。
114 1 Haru Iida
115 7 Haru Iida
@vendor/plugins/redmine_polls/app/controllers/polls_controller.rb@ を編集して 2つのアクションを実装します。
116 1 Haru Iida
117
<pre><code class="ruby">
118
class PollsController < ApplicationController
119
  unloadable
120
121
  def index
122
    @polls = Poll.find(:all)
123
  end
124
125
  def vote
126
    poll = Poll.find(params[:id])
127
    poll.vote(params[:answer])
128
    if poll.save
129
      flash[:notice] = 'Vote saved.'
130
      redirect_to :action => 'index'
131
    end
132
  end
133
end
134
</code></pre>
135
136 8 Haru Iida
そして @vendor/plugins/redmine_polls/app/views/polls/index.html.erb@ を編集すると先ほど作成した2つのpollを表示できます。:
137 1 Haru Iida
138
139
<pre>
140
<h2>Polls</h2>
141
142
<% @polls.each do |poll| %>
143
  <p>
144
  <%= poll[:question] %>?
145
  <%= link_to 'Yes', {:action => 'vote', :id => poll[:id], :answer => 'yes'}, :method => :post %> (<%= poll[:yes] %>) /
146
  <%= link_to 'No', {:action => 'vote', :id => poll[:id], :answer => 'no'}, :method => :post %> (<%= poll[:no] %>)
147
  </p>
148
<% end %>
149
</pre>
150
151 8 Haru Iida
@vendor/plugins/redmine_polls/app/views/polls/vote.html.erb@ は対応するactionから使われることがないので削除してよいです。
152 1 Haru Iida
153 8 Haru Iida
さあ、Redmineを再起動してブラウザから http://localhost:3000/polls にアクセスしましょう。
154
2つのpollが確認でき、それらに投票することができるでしょう。:
155 1 Haru Iida
156 8 Haru Iida
!pools1.png!
157 1 Haru Iida
158
Note that poll results are reset on each request if you don't run the application in production mode, since our poll "model" is stored in a class variable in this example.
159
160
h2. Extending menus
161
162
Our controller works fine but users have to know the url to see the polls. Using the Redmine plugin API, you can extend standard menus.
163
So let's add a new item to the application menu.
164
165
h3. Extending the application menu
166
167
Edit @vendor/plugins/redmine_polls/init.rb@ at the root of your plugin directory to add the following line at the end of the plugin registration block:
168
169
<pre><code class="ruby">
170
Redmine::Plugin.register :redmine_polls do
171
  [...]
172
  
173
  menu :application_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls'
174
end
175
</code></pre>
176
177
Syntax is:
178
179
  menu(menu_name, item_name, url, options={})
180
181
There are 4 menus that you can extend:
182
183
* @:top_menu@ - the top left menu
184
* @:account_menu@ - the top right menu with sign in/sign out links
185
* @:application_menu@ - the main menu displayed when the user is not inside a project
186
* @:project_menu@ - the main menu displayed when the user is inside a project
187
188
Available options are:
189
190
* @:param@ - the parameter key that is used for the project id (default is @:id@)
191
* @:if@ - a Proc that is called before rendering the item, the item is displayed only if it returns true
192
* @:caption@ - the menu caption that can be:
193
194
  * a localized string Symbol
195
  * a String
196
  * a Proc that can take the project as argument
197
198
* @:before@, @:after@ - specify where the menu item should be inserted (eg. @:after => :activity@)
199
* @:last@ - if set to true, the item will stay at the end of the menu (eg. @:last => true@)
200
* @:html_options@ - a hash of html options that are passed to @link_to@ when rendering the menu item
201
202
In our example, we've added an item to the application menu which is emtpy by default.
203
Restart the application and go to http://localhost:3000:
204
205
p=. !application_menu.png!
206
207
Now you can access the polls by clicking the Polls tab from the welcome screen.
208
209
h3. Extending the project menu
210
211
Now, let's consider that the polls are defined at project level (even if it's not the case in our example poll model). So we would like to add the Polls tab to the project menu instead.
212
Open @init.rb@ and replace the line that was added just before with these 2 lines:
213
214
<pre><code class="ruby">
215
Redmine::Plugin.register :redmine_polls do
216
  [...]
217
218
  permission :polls, {:polls => [:index, :vote]}, :public => true
219
  menu :project_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls', :after => :activity, :param => :project_id
220
end
221
</code></pre>
222
223
The second line adds our Polls tab to the project menu, just after the activity tab.
224
The first line is required and declares that our 2 actions from @PollsController@ are public. We'll come back later to explain this with more details.
225
226
Restart the application again and go to one of your projects:
227
228
p=. !project_menu.png!
229
230
If you click the Polls tab, you should notice that the project menu is no longer displayed.
231
To make the project menu visible, you have to initialize the controller's instance variable @@project@.
232
233
Edit your PollsController to do so:
234
235
<pre><code class="ruby">
236
def index
237
  @project = Project.find(params[:project_id])
238
  @polls = Poll.find(:all) # @project.polls
239
end
240
</code></pre>
241
242
The project id is available in the @:project_id@ param because of the @:param => :project_id@ option in the menu item declaration above.
243
244
Now, you should see the project menu when viewing the polls:
245
246
p=. !project_menu_pools.png!
247
248
h2. Adding new permissions
249
250
For now, anyone can vote for polls. Let's make it more configurable by changing the permission declaration.
251
We're going to declare 2 project based permissions, one for viewing the polls and an other one for voting. These permissions are no longer public (@:public => true@ option is removed).
252
253
Edit @vendor/plugins/redmine_polls/init.rb@ to replace the previous permission declaration with these 2 lines:
254
255
<pre><code class="ruby">
256
257
  permission :view_polls, :polls => :index
258
  permission :vote_polls, :polls => :vote
259
</code></pre>
260
261
262
Restart the application and go to http://localhost:3000/roles/report:
263
264
p=. !permissions1.png!
265
266
You're now able to give these permissions to your existing roles.
267
268
Of course, some code needs to be added to the PollsController so that actions are actually protected according to the permissions of the current user.
269
For this, we just need to append the @:authorize@ filter and make sure that the @project instance variable is properly set before calling this filter.
270
271
Here is how it would look like for the @#index@ action:
272
273
<pre><code class="ruby">
274
class PollsController < ApplicationController
275
  unloadable
276
  
277
  before_filter :find_project, :authorize, :only => :index
278
279
  [...]
280
  
281
  def index
282
    @polls = Poll.find(:all) # @project.polls
283
  end
284
285
  [...]
286
  
287
  private
288
  
289
  def find_project
290
    # @project variable must be set before calling the authorize filter
291
    @project = Project.find(params[:project_id])
292
  end
293
end
294
</code></pre>
295
296
Retrieving the current project before the @#vote@ action could be done using a similar way.
297
After this, viewing and voting polls will be only available to admin users or users that have the appropriate role on the project.
298
299
h2. Creating a project module
300
301
For now, the poll functionality is added to all your projects. But you way want to enable polls for some projects only.
302
So, let's create a 'Polls' project module. This is done by wrapping the permissions declaration inside a call to @#project_module@.
303
304
Edit @init.rb@ and change the permissions declaration:
305
306
<pre><code class="ruby">
307
  project_module :polls do
308
    permission :view_polls, :polls => :index
309
    permission :vote_polls, :polls => :vote
310
  end
311
</code></pre>
312
313
Restart the application and go to one of your project settings.
314
Click on the Modules tab. You should see the Polls module at the end of the modules list (disabled by default):
315
316
p=. !modules.png!
317
318
You can now enable/disable polls at project level.
319
320
h2. Improving the plugin views
321
322
h3. Adding stylesheets
323
324
Let's start by adding a stylesheet to our plugin views.
325
Create a file named @voting.css@ in the @vendor/plugins/redmine_polls/assets/stylesheets@ directory:
326
327
<pre>
328
a.vote { font-size: 120%; }
329
a.vote.yes { color: green; }
330
a.vote.no  { color: red; }
331
</pre>
332
333
When starting the application, plugin assets are automatically copied to @public/plugin_assets/redmine_polls/@ by Rails Engines to make them available through your web server. So any change to your plugin stylesheets or javascripts needs an application restart.
334
335
Then, append the following lines at the end of @vendor/plugins/redmine_polls/app/views/polls/index.html.erb@ so that your stylesheet get included in the page header by Redmine:
336
337
<pre>
338
<% content_for :header_tags do %>
339
    <%= stylesheet_link_tag 'voting', :plugin => 'redmine_polls' %>
340
<% end %>
341
</pre>
342
343
Note that the @:plugin => 'redmine_polls'@ option is required when calling the @stylesheet_link_tag@ helper.
344
345
Javascripts can be included in plugin views using the @javascript_include_tag@ helper in the same way.
346
347
h3. Setting page title
348
349
You can set the HTML title from inside your views by using the @html_title@ helper.
350
Example:
351
352
  <% html_title "Polls" -%>