プロジェクト

全般

プロフィール

GuideNewAction » 履歴 » バージョン 9

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

1 1 Mitsuyoshi Yoshida
h1. 新規作成(new) アクション
2
3 6 Mitsuyoshi Yoshida
新しいデータを作成するためのアクションを実装します。
4 1 Mitsuyoshi Yoshida
このページは一覧表示ページから呼ばれることになります。
5
6
7
h2. 新規作成ページの仕様
8
9
まず、作成する新規作成ページの動きについてもう少し細かく決めておきましょう。
10
新規作成ページではパラメータを指定して、新しいデータを作成することになります。サンプルでは題名(subject)と説明(decription)です。説明は wiki で記述できるようにします。通常の wiki のように添付ファイルやプレビューまでつけようとすると少し複雑になりますが、 wiki 形式にするだけならば結構簡単にできます。
11 5 Mitsuyoshi Yoshida
それらの機能が付いた wiki の作成については [[Tips wiki|プラグイン Tips]] を見てください。
12 1 Mitsuyoshi Yoshida
13
!new.png!
14
15
チケットでは [作成] ボタンを押すとチケットが作成されて詳細情報のページになります。サンプルでも [作成] 後には詳細説明のページになるようにします。
16
また、チケットと同様に題名に何も入力されていないとエラーメッセージがでて、データが作成されないようにもします。
17
18
19
20 8 NAITOH Jun
h2. GET と POST と PUT
21 1 Mitsuyoshi Yoshida
22 9 NAITOH Jun
コントローラ → ビュー のデータのデータの受け渡しではインスタンス変数を使用することが出来ました。 create では逆に ビュー → コントローラ の方向でデータを受け渡す必要があります。Rails ではこの場合 CGI の GET や POST や PUT を使ってデータを受け取ることになります。
23 1 Mitsuyoshi Yoshida
24
よく検索サイトや辞書サイトではアドレスの後に ? が付いていろいろとパラメータが設定されていると思います。このようにアドレスにつけてパラメータを渡す方法を *GET* といいます。この方法の利点はアドレスにつけて渡すので、検索条件込みでリンクをつくることができる点です。プラグインを作る場合でもフィルタなどの検索を使う場合にはパラメータの受け渡しには GET を使った方がいいでしょう。
25 9 NAITOH Jun
[[GuideForProject|プロジェクトメニューのリンク]] では project_id の値をパラメータとして渡していました。これは GET でパラメータを渡すことになります。 Rails では url の指定をパスやハッシュで行った場合、コントロール、アクション、 ID 以外のパラメータはデフォルトでは GET として渡されるためです。
26 1 Mitsuyoshi Yoshida
27 9 NAITOH Jun
GET ではアドレスとしてパラメータを持たせるため、あまり長いパラメータの場合には不向きですし、 255 文字という制限があります。その場合には *POST* (もしくは *PUT*)を使ってデータを送信することになります。 Rails ではフォームでパラメータを送ろうとするとデフォルトは新規作成の場合は *POST* 、更新の場合は *PUT* でデータを送信します。
28 1 Mitsuyoshi Yoshida
29 8 NAITOH Jun
ただし、 Rails では受け取る場合その違いを意識する必要はありません。 GET や POST、PUT で受け渡されるデータはキーと値のペアなのですが、これらは params 変数のハッシュの中に格納されます。
30 1 Mitsuyoshi Yoshida
つまり、 ビュー → コントローラでデータを受け取る場合には params 変数で行うことになります。
31
32
!view_control.png!
33
34
h2. コントローラの実装
35
36 9 NAITOH Jun
コントローラ(app/controllers/foos_controller.rb) の new および create メソッドを実装します。 
37 1 Mitsuyoshi Yoshida
38 9 NAITOH Jun
h3. 新規作成フォーム( new アクション )
39
40 1 Mitsuyoshi Yoshida
<pre><code class="ruby">
41 9 NAITOH Jun
    @foo = Foo.new()
42
</code></pre>
43
44
new アクションは一覧表示のリンクから呼び出されます。
45
Foo モデルクラスのオブジェクトを新規作成します。
46
47
h3. 作成( create アクション )
48
49
続いて create メソッドを実装します。 
50
51
create はコントローラのスケルトンで作成していませんでした。そこで中身だけでなく、定義からコントローラ(foos_controller.rb)に記述することになります。
52
53
<pre><code class="ruby">
54
  def create
55 1 Mitsuyoshi Yoshida
    @foo = Foo.new(params[:foo])
56
    @foo.project_id = @project.id
57
58 9 NAITOH Jun
    if @foo.save	
59 1 Mitsuyoshi Yoshida
      flash[:notice] = l(:notice_successful_create)
60 9 NAITOH Jun
      redirect_to project_foo_path(@project, @foo.id)
61 1 Mitsuyoshi Yoshida
    end
62 9 NAITOH Jun
  end
63 1 Mitsuyoshi Yoshida
</code></pre>
64
65 9 NAITOH Jun
新規作成画面で [作成] ボタンが押された後、create アクションが実行されます。
66 1 Mitsuyoshi Yoshida
67 9 NAITOH Jun
@params[:foo]@ は、 :foo をキーとした場合にはハッシュになっていて、そこに :subject や :description をキーとして値が入っています。例えば説明の中身を取り出したい場合は @params[:foo][:description]@ でアクセスすることが出来ます。
68 1 Mitsuyoshi Yoshida
Foo.new の引数として、このハッシュを渡すことでメンバにそのハッシュの中身が格納されたオブジェクトが作成されます。
69
70 9 NAITOH Jun
save はオブジェクトの中身をレコードとしてデータベースに保存する Foo モデルのメソッドです。
71 1 Mitsuyoshi Yoshida
72 9 NAITOH Jun
保存が成功したあとに実行されているコードはチップの作成時にでてくるような"作成されたました"といったメッセージを出力するためのものです。
73
その後 *redirect_to* を使い project_foo_path に変更しています。これにより新規作成ページではなく、詳細ページが表示されることになります。 redirect_to に渡す引数はリンクなどでの URL 指定の場合と同じです。
74 1 Mitsuyoshi Yoshida
75
76
h2. ビューの実装
77
78
次にビュー (app/views/foos/new.html.erb) を実装します。
79 8 NAITOH Jun
80 9 NAITOH Jun
<pre><code class="erb">
81
<%= labelled_form_for :foo, @foo,
82
                  :url => project_foos_path(@project) do |f| %>
83 1 Mitsuyoshi Yoshida
    <%= render :partial => 'foos/form', :locals => {:form => f} %>
84
    <%= f.submit l(:button_create) %>
85
<% end %>
86
</code></pre>
87
88
89
h3. 部分描画
90
91
新規作成と編集ページではほぼ同じ画面となります。 同じようなことを何度も書くのは DRY じゃありません
92 8 NAITOH Jun
他のプログラミングでは同じような部分があった場合、共通部分を関数として抜き出したりします。 Rails のビューの描画でも同様に共通の描画部分を分けることが出来ます。
93 1 Mitsuyoshi Yoshida
94
それが new.html.erb の 2 行目の render の部分になります。
95
*":partial=>'foos/form'* で共通部分を記述しているファイルを指定しています。指定は app/views 以下のパスで指定するのですが、実際のファイルは *app/views/foos/_form.html.erb* となります。つまり、実際には先頭に _ アンダーバーを付けて、拡張子を付加したものが検索されます。
96
関数に引数を渡すようなことが *:locals* で出来ます。ここでは f で指定されたオブジェクトが部分描画のファイル内では form という変数名で使用できるようにになります。
97
98
99 8 NAITOH Jun
h3. フォーム
100 1 Mitsuyoshi Yoshida
101
new では作成時のパラメータの設定に html のフォームを使います。 *labelled_form_for* は Rails で通常使われる *form_for* メソッドをを拡張したもので、フォーム内のラベルとフィールドがテーブルのように配列されます。methodの引数は form_for と同じです。
102 3 Mitsuyoshi Yoshida
103 8 NAITOH Jun
第一引数はフォームの名前です。:foo を指定していますのでフォーム内で指定されるパラメータは params[:foo] のハッシュに格納されることになります。
104 1 Mitsuyoshi Yoshida
第二引数はモデルクラスのオブジェクトを指定します。このオブジェクトの各メンバの値が対応するパラメータのフィールドにおけるデフォルト値となります。ただし、Foo.new される際特にメンバにデフォルト値を設定していませんので、各パラメータのデフォルト値は空文字になります。
105 9 NAITOH Jun
第三引数は *:url* シンボルを使ってパスを指定します。ここでは自動的に POST として処理されるため create アクションが実行されることになります。 id 省略時には現在のものが使用されます。なお、リンクの url 指定の場合には id は省略されると空になるので省略はできません。
106 1 Mitsuyoshi Yoshida
107
labelled_form_for のメソッドのブロック内でフォームの各フィールドを設定します。各フィールドは f.submit ボタンのようにブロックの引数 @f@ を使って設定します。
108
109
110 8 NAITOH Jun
h3. フォーム内のパラメータ
111 1 Mitsuyoshi Yoshida
112
app/views/foos/_form.html.erb の中身は次のようになります。
113
114 9 NAITOH Jun
<pre><code class="erb">
115 1 Mitsuyoshi Yoshida
<%= error_messages_for 'foo' %>
116
<div class="box">
117
<p><%= form.text_field :subject,
118
                       :size => 100, :required => true %></p>
119
<p><%= form.text_area :description,
120
                      :class => 'wiki-edit' %></p>
121
<%= wikitoolbar_for 'foo_description' %>
122
</div>
123
</code></pre>
124
125
これが new.html.erb の render :partial の部分に入ることになります。
126
127
1 行目ではエラーメッセージの表示を指定しています。 foo という名前のフォーム内で入力にエラーがあった場合にエラーメッセージが表示されるようになっています。
128
129 8 NAITOH Jun
*box* クラスのブロックは設定ダイアログのように背景を灰色にするためのものです。
130 1 Mitsuyoshi Yoshida
131
:locals のオプションで設定したようにこのファイル内では form が labelled_form_for のブロック変数です。これを使ってパラメータ用の各フィールドが配置されています。
132
133
|_. 対象 |_. パラメータ名 |_. フィールドタイプ |_. ラベルのシンボル |
134
| 題名 | subject | テキストフィールド | field_subject |
135
| 説明 | description | テキストエリア | field_description |
136
137
ラベルは省略しているため、 *field_パラメータ名* というシンボルに対応するメッセージが使用されます。それぞれのメッセージ定義は Redmine のメッセージファイルにあります。
138
139
subject テキストフィールドのオプションでは、まずデフォルトでは幅が少し短いので :size で幅を指定しています。 次の :required オプションで true を指定しています。これは必ず入力しなければならないことを表す  %{color:red}*% を付けるためのものです。ただし、これはマークを付けているだけでこのオプションで空文字の入力のエラー判定まで行ってくれるわけではありません。エラーチェックをする方法は次節で実装します。
140 4 Mitsuyoshi Yoshida
141 1 Mitsuyoshi Yoshida
description テキストエリアでは wiki 入力ようにするため 2 つのことを行っています。
142
143
* CSS の *wiki-edit* クラスにする
144
* *wikitoolbar_for* メソッドで wiki 編集用のツールボックスをつける
145
  引数で foo フィールドの description のテキストエリアを指定
146
147
148 8 NAITOH Jun
h2. モデルの実装
149 1 Mitsuyoshi Yoshida
150
パラメータの値が妥当かどうかのチェックはモデル (app/models/foo.rb) に記述します。
151
この処理は ActiveRecord::Base クラスの *validate* メソッドをオーバーライドして実装します。しかし、空文字のチェックなどよく使われるチェックには便利なメソッドが用意されています。サンプルではこちらを使用します。
152
153
<pre><code class="ruby">
154
class Foo < ActiveRecord::Base
155
  unloadable
156
157
  validates_presence_of :subject
158
  validates_length_of :subject, :maximum => 255
159
160
end
161
</code></pre>
162
163
スケルトンで出力されたものに 4, 5 行目を追加しています。
164
4 行目の *validates_presence_of* で subject パラメータで未設定(空文字)を禁止しています。
165
5 行目の *validates_length_of* で subject パラメータの文字数の最大値を指定しています。 subject は string 型なので 255 文字の制限がありました。そのため 255 文字以上入力するとエラーとなるようにしています。
166
167
168
---
169
170
| [[プラグイン開発ガイド|^]] | [[GuideIndexAction|<<]] | [[GuideActionElse|>>]] |