プロジェクト

全般

プロフィール

操作

GuideNewAction » 履歴 » リビジョン 7

« 前 | リビジョン 7/9 (差分) | 次 »
Mitsuyoshi Yoshida, 2012/01/18 23:35


新規作成(new) アクション

新しいデータを作成するためのアクションを実装します。
このページは一覧表示ページから呼ばれることになります。

新規作成ページの仕様

まず、作成する新規作成ページの動きについてもう少し細かく決めておきましょう。
新規作成ページではパラメータを指定して、新しいデータを作成することになります。サンプルでは題名(subject)と説明(decription)です。説明は wiki で記述できるようにします。通常の wiki のように添付ファイルやプレビューまでつけようとすると少し複雑になりますが、 wiki 形式にするだけならば結構簡単にできます。
それらの機能が付いた wiki の作成については プラグイン Tips を見てください。

チケットでは [作成] ボタンを押すとチケットが作成されて詳細情報のページになります。サンプルでも [作成] 後には詳細説明のページになるようにします。
また、チケットと同様に題名に何も入力されていないとエラーメッセージがでて、データが作成されないようにもします。

GET と POST

コントローラ → ビュー のデータのデータの受け渡しではインスタンス変数を使用することが出来ました。 new では逆に ビュー → コントローラ の方向でデータを受け渡す必要があります。Rails ではこの場合 CGI の GET や POST を使ってデータを受け取ることになります。

よく検索サイトや辞書サイトではアドレスの後に ? が付いていろいろとパラメータが設定されていると思います。このようにアドレスにつけてパラメータを渡す方法を GET といいます。この方法の利点はアドレスにつけて渡すので、検索条件込みでリンクをつくることができる点です。プラグインを作る場合でもフィルタなどの検索を使う場合にはパラメータの受け渡しには GET を使った方がいいでしょう。
プロジェクトメニューのリンク では project_id の値をパラメータとして渡していました。これは GET でパラメータを渡すことになります。 Rails では url の指定をハッシュで行った場合、コントロール、アクション、 ID 以外のパラメータはデフォルトでは GET として渡されるためです。

GET ではアドレスとしてパラメータを持たせるため、あまり長いパラメータの場合には不向きですし、 255 文字という制限があります。その場合には POST を使ってデータを送信することになります。 Rails ではフォームでパラメータを送ろうとするとデフォルトは POST となります。
この新規作成ページの場合も POST でデータを送信します。

ただし、 Rails では受け取る場合その違いを意識する必要はありません。 GET や POST で受け渡されるデータはキーと値のペアなのですが、これらは params 変数のハッシュの中に格納されます。
つまり、 ビュー → コントローラでデータを受け取る場合には params 変数で行うことになります。

コントローラの実装

コントローラ(app/controllers/foos_controller.rb) の new メソッドを実装します。

    @foo = Foo.new(params[:foo])
    @foo.project_id = @project.id

    if request.post? and @foo.save    
      flash[:notice] = l(:notice_successful_create)
      redirect_to :action => 'show', :project_id => @project, :id => @foo.id
    end

new アクションは一覧表示のリンクから呼び出されます。しかし、それだけでなく新規作成画面で [作成] ボタンが押された後、再度 new アクションが実行されることになります。

Foo モデルクラスのオブジェクトを新規作成して、 project_id メンバに現在のプロジェクト(@project) の id を設定しています。
このとき引数として params の :foo の値が渡されています。一覧表示から呼び出された場合には、この中は空なので、通常のオブジェクトの作成と同じです。

[作成] から呼び出された場合には params[:foo] に値が入っています。 :foo をキーとした値の中はさらにハッシュになっていて、そこに :subject や :description をキーとして値が入っています。例えば説明の中身を取り出したい場合は params[:foo][:description] でアクセスすることが出来ます。
Foo.new の引数として、このハッシュを渡すことでメンバにそのハッシュの中身が格納されたオブジェクトが作成されます。

request.post? は POST が実行されたかどうかです。そのため、一覧表示のリンクから呼ばれた場合は偽となり、メソッドを抜けて new.html.erb が作成、表示されます。

[作成] から呼び出された場合、 @foo.save が実行されます。 save はオブジェクトの中身をレコードとしてデータベースに保存する Foo モデルのメソッドです。

POST でかつ保存も成功したあとに実行されているコードはチップの作成時にでてくるような"作成されたました"といったメッセージを出力するためのものです。
その後 redirect_to を使い、show アクションに変更しています。これにより新規作成ページではなく、詳細ページが表示されることになります。 redirect_to に渡す引数はリンクなどでのアクション指定の場合と同じです。

ビューの実装

次にビュー (app/views/foos/new.html.erb) を実装します。

<% labelled_tabular_form_for :foo, @foo, {} do |f| %>
    <%= render :partial => 'foos/form', :locals => {:form => f} %>
    <%= f.submit l(:button_create) %>
<% end %>

部分描画

新規作成と編集ページではほぼ同じ画面となります。 同じようなことを何度も書くのは DRY じゃありません
他のプログラミングでは同じような部分があった場合、共通部分を関数として抜き出したりします。 Rails のビューの描画でも同様に共通の描画部分を分けることが出来ます。

それが new.html.erb の 2 行目の render の部分になります。
":partial=>'foos/form' で共通部分を記述しているファイルを指定しています。指定は app/views 以下のパスで指定するのですが、実際のファイルは app/views/foos/_form.index.html.erb となります。つまり、実際には先頭に _ アンダーバーを付けて、拡張子を付加したものが検索されます。
関数に引数を渡すようなことが :locals で出来ます。ここでは f で指定されたオブジェクトが部分描画のファイル内では form という変数名で使用できるようにになります。

フォーム

new では作成時のパラメータの設定に html のフォームを使います。 labelled_tabular_form_for は Rails で通常使われる form_for メソッドをを拡張したもので、フォーム内のラベルとフィールドがテーブルのように配列されます。methodの引数は form_for と同じです。

第一引数はフォームの名前です。:foo を指定していますのでフォーム内で指定されるパラメータは params[:foo] のハッシュに格納されることになります。
第二引数はモデルクラスのオブジェクトを指定します。このオブジェクトの各メンバの値が対応するパラメータのフィールドにおけるデフォルト値となります。ただし、Foo.new される際特にメンバにデフォルト値を設定していませんので、各パラメータのデフォルト値は空文字になります。
第三引数はオプションです。通常ここで :url シンボルを使って、ハッシュでアクションを指定するのですが省略しています。コントローラを省略するとカレントのコントローラを指定したことになりました。同様にアクションを省略するとカレントのアクションになります。ここでは両方とも省略しているため、 自身の new アクションが指定されたことになります。また、id も省略時には現在のものが使用されます。なお、リンクの url 指定の場合には id は省略されると空になるので省略はできません。

labelled_tabular_form_for のメソッドのブロック内でフォームの各フィールドを設定します。各フィールドは f.submit ボタンのようにブロックの引数 f を使って設定します。

フォーム内のパラメータ

app/views/foos/_form.index.html.erb の中身は次のようになります。

<%= error_messages_for 'foo' %>
<div class="box">
<p><%= form.text_field :subject,
                       :size => 100, :required => true %></p>
<p><%= form.text_area :description,
                      :class => 'wiki-edit' %></p>
<%= wikitoolbar_for 'foo_description' %>
</div>

これが new.html.erb の render :partial の部分に入ることになります。

1 行目ではエラーメッセージの表示を指定しています。 foo という名前のフォーム内で入力にエラーがあった場合にエラーメッセージが表示されるようになっています。

box クラスのブロックは設定ダイアログのように背景を灰色にするためのものです。

:locals のオプションで設定したようにこのファイル内では form が labelled_tabular_form_for のブロック変数です。これを使ってパラメータ用の各フィールドが配置されています。

対象 パラメータ名 フィールドタイプ ラベルのシンボル
題名 subject テキストフィールド field_subject
説明 description テキストエリア field_description

ラベルは省略しているため、 field_パラメータ名 というシンボルに対応するメッセージが使用されます。それぞれのメッセージ定義は Redmine のメッセージファイルにあります。

subject テキストフィールドのオプションでは、まずデフォルトでは幅が少し短いので :size で幅を指定しています。 次の :required オプションで true を指定しています。これは必ず入力しなければならないことを表す * を付けるためのものです。ただし、これはマークを付けているだけでこのオプションで空文字の入力のエラー判定まで行ってくれるわけではありません。エラーチェックをする方法は次節で実装します。

description テキストエリアでは wiki 入力ようにするため 2 つのことを行っています。

  • CSS の wiki-edit クラスにする
  • wikitoolbar_for メソッドで wiki 編集用のツールボックスをつける
    引数で foo フィールドの description のテキストエリアを指定

モデルの実装

パラメータの値が妥当かどうかのチェックはモデルに記述します。
この処理は ActiveRecord::Base クラスの validate メソッドをオーバーライドして実装します。しかし、空文字のチェックなどよく使われるチェックには便利なメソッドが用意されています。サンプルではこちらを使用します。

class Foo < ActiveRecord::Base
  unloadable

  validates_presence_of :subject
  validates_length_of :subject, :maximum => 255

end

スケルトンで出力されたものに 4, 5 行目を追加しています。
4 行目の validates_presence_of で subject パラメータで未設定(空文字)を禁止しています。
5 行目の validates_length_of で subject パラメータの文字数の最大値を指定しています。 subject は string 型なので 255 文字の制限がありました。そのため 255 文字以上入力するとエラーとなるようにしています。


^ << >>


Updated by Mitsuyoshi Yoshida , 12年以上前に更新
Access count: 28033 :since 2009-10-30

Mitsuyoshi Yoshida さんが12年以上前に更新 · 7件の履歴