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