プロジェクト

全般

プロフィール

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

Haru Iida, 2009/05/28 15:47

1 1 Haru Iida
www.redmine.orgの"Plugin Turorial":http://www.redmine.org/wiki/redmine/Plugin_Tutorial を和訳してみます。
2
3
h1. プラグイン チュートリアル
4
5
注意: このチュートリアルはRedmineの開発リビジョン r1786 以上を対象にしています。
6
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
Lets add some Polls in the console so we have something to work with.  The console is where you an interactively work and examine the Redmine environment and is very informative to play around in.  But for now we just need create two Poll objects
74
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
Edit @vendor/plugins/redmine_polls/app/models/poll.rb@ in your plugin directory to add a #vote method that will be invoked from our controller:
83
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
h2. Generating a controller
93
94
For now, the plugin doesn't do anything. So let's create a controller for our plugin.
95
We can use the plugin controller generator for that. Syntax is:
96
97
<pre>ruby script/generate redmine_plugin_controller <plugin_name> <controller_name> [<actions>]</pre>
98
99
So go back to the command prompt and run:
100
101
<pre>
102
% ruby script/generate redmine_plugin_controller Polls polls index vote
103
      exists  app/controllers/
104
      exists  app/helpers/
105
      create  app/views/polls
106
      create  test/functional/
107
      create  app/controllers/polls_controller.rb
108
      create  test/functional/polls_controller_test.rb
109
      create  app/helpers/polls_helper.rb
110
      create  app/views/polls/index.html.erb
111
      create  app/views/polls/vote.html.erb
112
</pre>
113
114
A controller @PollsController@ with 2 actions (@#index@ and @#vote@) is created.
115
116
Edit @vendor/plugins/redmine_polls/app/controllers/polls_controller.rb@ in @redmine_polls@ directory to implement these 2 actions.
117
118
<pre><code class="ruby">
119
class PollsController < ApplicationController
120
  unloadable
121
122
  def index
123
    @polls = Poll.find(:all)
124
  end
125
126
  def vote
127
    poll = Poll.find(params[:id])
128
    poll.vote(params[:answer])
129
    if poll.save
130
      flash[:notice] = 'Vote saved.'
131
      redirect_to :action => 'index'
132
    end
133
  end
134
end
135
</code></pre>
136
137
Then edit @vendor/plugins/redmine_polls/app/views/polls/index.html.erb@ that will display existing polls:
138
139
140
<pre>
141
<h2>Polls</h2>
142
143
<% @polls.each do |poll| %>
144
  <p>
145
  <%= poll[:question] %>?
146
  <%= link_to 'Yes', {:action => 'vote', :id => poll[:id], :answer => 'yes'}, :method => :post %> (<%= poll[:yes] %>) /
147
  <%= link_to 'No', {:action => 'vote', :id => poll[:id], :answer => 'no'}, :method => :post %> (<%= poll[:no] %>)
148
  </p>
149
<% end %>
150
</pre>
151
152
You can remove @vendor/plugins/redmine_polls/app/views/polls/vote.html.erb@ since no rendering is done by the corresponding action.
153
154
Now, restart the application and point your browser to http://localhost:3000/polls.
155
You should see the 2 polls and you should be able to vote for them:
156
157
p=. !pools1.png!
158
159
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.
160
161
h2. Extending menus
162
163
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.
164
So let's add a new item to the application menu.
165
166
h3. Extending the application menu
167
168
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:
169
170
<pre><code class="ruby">
171
Redmine::Plugin.register :redmine_polls do
172
  [...]
173
  
174
  menu :application_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls'
175
end
176
</code></pre>
177
178
Syntax is:
179
180
  menu(menu_name, item_name, url, options={})
181
182
There are 4 menus that you can extend:
183
184
* @:top_menu@ - the top left menu
185
* @:account_menu@ - the top right menu with sign in/sign out links
186
* @:application_menu@ - the main menu displayed when the user is not inside a project
187
* @:project_menu@ - the main menu displayed when the user is inside a project
188
189
Available options are:
190
191
* @:param@ - the parameter key that is used for the project id (default is @:id@)
192
* @:if@ - a Proc that is called before rendering the item, the item is displayed only if it returns true
193
* @:caption@ - the menu caption that can be:
194
195
  * a localized string Symbol
196
  * a String
197
  * a Proc that can take the project as argument
198
199
* @:before@, @:after@ - specify where the menu item should be inserted (eg. @:after => :activity@)
200
* @:last@ - if set to true, the item will stay at the end of the menu (eg. @:last => true@)
201
* @:html_options@ - a hash of html options that are passed to @link_to@ when rendering the menu item
202
203
In our example, we've added an item to the application menu which is emtpy by default.
204
Restart the application and go to http://localhost:3000:
205
206
p=. !application_menu.png!
207
208
Now you can access the polls by clicking the Polls tab from the welcome screen.
209
210
h3. Extending the project menu
211
212
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.
213
Open @init.rb@ and replace the line that was added just before with these 2 lines:
214
215
<pre><code class="ruby">
216
Redmine::Plugin.register :redmine_polls do
217
  [...]
218
219
  permission :polls, {:polls => [:index, :vote]}, :public => true
220
  menu :project_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls', :after => :activity, :param => :project_id
221
end
222
</code></pre>
223
224
The second line adds our Polls tab to the project menu, just after the activity tab.
225
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.
226
227
Restart the application again and go to one of your projects:
228
229
p=. !project_menu.png!
230
231
If you click the Polls tab, you should notice that the project menu is no longer displayed.
232
To make the project menu visible, you have to initialize the controller's instance variable @@project@.
233
234
Edit your PollsController to do so:
235
236
<pre><code class="ruby">
237
def index
238
  @project = Project.find(params[:project_id])
239
  @polls = Poll.find(:all) # @project.polls
240
end
241
</code></pre>
242
243
The project id is available in the @:project_id@ param because of the @:param => :project_id@ option in the menu item declaration above.
244
245
Now, you should see the project menu when viewing the polls:
246
247
p=. !project_menu_pools.png!
248
249
h2. Adding new permissions
250
251
For now, anyone can vote for polls. Let's make it more configurable by changing the permission declaration.
252
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).
253
254
Edit @vendor/plugins/redmine_polls/init.rb@ to replace the previous permission declaration with these 2 lines:
255
256
<pre><code class="ruby">
257
258
  permission :view_polls, :polls => :index
259
  permission :vote_polls, :polls => :vote
260
</code></pre>
261
262
263
Restart the application and go to http://localhost:3000/roles/report:
264
265
p=. !permissions1.png!
266
267
You're now able to give these permissions to your existing roles.
268
269
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.
270
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.
271
272
Here is how it would look like for the @#index@ action:
273
274
<pre><code class="ruby">
275
class PollsController < ApplicationController
276
  unloadable
277
  
278
  before_filter :find_project, :authorize, :only => :index
279
280
  [...]
281
  
282
  def index
283
    @polls = Poll.find(:all) # @project.polls
284
  end
285
286
  [...]
287
  
288
  private
289
  
290
  def find_project
291
    # @project variable must be set before calling the authorize filter
292
    @project = Project.find(params[:project_id])
293
  end
294
end
295
</code></pre>
296
297
Retrieving the current project before the @#vote@ action could be done using a similar way.
298
After this, viewing and voting polls will be only available to admin users or users that have the appropriate role on the project.
299
300
h2. Creating a project module
301
302
For now, the poll functionality is added to all your projects. But you way want to enable polls for some projects only.
303
So, let's create a 'Polls' project module. This is done by wrapping the permissions declaration inside a call to @#project_module@.
304
305
Edit @init.rb@ and change the permissions declaration:
306
307
<pre><code class="ruby">
308
  project_module :polls do
309
    permission :view_polls, :polls => :index
310
    permission :vote_polls, :polls => :vote
311
  end
312
</code></pre>
313
314
Restart the application and go to one of your project settings.
315
Click on the Modules tab. You should see the Polls module at the end of the modules list (disabled by default):
316
317
p=. !modules.png!
318
319
You can now enable/disable polls at project level.
320
321
h2. Improving the plugin views
322
323
h3. Adding stylesheets
324
325
Let's start by adding a stylesheet to our plugin views.
326
Create a file named @voting.css@ in the @vendor/plugins/redmine_polls/assets/stylesheets@ directory:
327
328
<pre>
329
a.vote { font-size: 120%; }
330
a.vote.yes { color: green; }
331
a.vote.no  { color: red; }
332
</pre>
333
334
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.
335
336
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:
337
338
<pre>
339
<% content_for :header_tags do %>
340
    <%= stylesheet_link_tag 'voting', :plugin => 'redmine_polls' %>
341
<% end %>
342
</pre>
343
344
Note that the @:plugin => 'redmine_polls'@ option is required when calling the @stylesheet_link_tag@ helper.
345
346
Javascripts can be included in plugin views using the @javascript_include_tag@ helper in the same way.
347
348
h3. Setting page title
349
350
You can set the HTML title from inside your views by using the @html_title@ helper.
351
Example:
352
353
  <% html_title "Polls" -%>