Last-modified: 2010-09-22 (水) 16:37:55 (11h)

Rails Form helpers

原文

http://guides.rubyonrails.org/form_helpers.html

フォームヘルパ(Rails Form helpers)

Web アプリケーション内のフォームは、ユーザーの入力のための本質的なインターフェイスです。
しかしながら、フォームのマークアップは、フォームコントロールの命名と、数多くの属性のために
すぐに書くのと維持するのが退屈になります。
フォームのマークアップを生成するためのビューヘルパの提供により、
Rails はこれらの複雑さを遠くのほうにやってしまえます。
しかしながら、様々なユースケースがあるので、
開発者は、使用するのに配置する前に、似た様なヘルパメソッド間の全ての違いを知っている必要があります。

このガイドでは:

  • 検索フォームや、アプリケーション内の特定のモデルを表さない一般的な同種のフォーム、の作成
  • 作成用のモデル中心のフォームの作成と、特定のデータベースレコードの編集
  • データの複数の型からセレクトボックスの生成
  • Rails が提供している、日付と時刻のヘルパーの理解
  • ファイルアップロードフォームの違いを学ぶ
  • 複雑なフォームの場所の探し方

このガイドは、利用可能なフォームヘルパーとその引数の完全なドキュメントであることを意図されていません。
完全なリファレンスはRails APIドキュメントを訪れて下さい。

1 基本的なフォームの処理(Dealing with Basic Forms)

最も基本的なフォームヘルパーはのform_tagです。

<%= form_tag do %>
  Form contents
<% end %>

このように、引数なしで呼ばれた場合、
そのアクションとして現在のページを持ち、そのメソッドとして "post" を持つ、フォーム要素を作成します。
(可読性のために、いくつかの改行が追加されます。)

form_tag のサンプル出力:

<form action="/home/index" method="post">
  <div style="margin:0;padding:0">
    <input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
  </div>
  Form contents
</form>

この出力を注意深く観察すると、あなたが指定していない何かをヘルパが生成していることに気づくでしょう:
内側に hidden の input を持つ div エレメントです。
これは、クロスサイトリクエストフォージェリの保護と呼ばれる Rails のセキュリティ機能で、
フォームヘルパは、アクションが "get" でない全てのフォームで、それを生成しています。(このセキュリティ機能が有効になっていれば)
Ruby On Rails Security Guide で、これについてもっと読むことができます。

このガイド内では、わかりやすいコードサンプルのために、この hidden の input を持つ div は省略されます。

1.1 汎用検索フォーム(A Generic Search Form)

しばしば、ウェブ上で見られるおそらく最小のフォームは、検索する言葉のための単一テキスト入力がある検索フォームです。
このフォームの構成は:

  1. "GET" メソッドを持つ form 要素
  2. 入力のための label
  3. テキスト入力要素
  4. submit 要素

検索フォームのメソッドとして "GET" を常に使うべきです。
このことは、ユーザーに特定の検索をブックマークし、戻ってこれることを許しています。
もっと一般的に Rails はアクションのために正しい HTTP verb を使用することを推奨します。

このフォームを作るために、 form_tag 、 label_tag 、 text_field_tag 、 submit_tag をそれぞれ使うでしょう。

基本的な検索フォーム

<%= form_tag(search_path, :method => "get") do %>
  <%= label_tag(:q, "Search for:") %>
  <%= text_field_tag(:q) %>
  <%= submit_tag("Search") %>
<% end %>

search_path は "routes.rb" 内で指定された名前付きルートでしょう:
map.search "search", :controller => "search"

上記のビューのコードは次のマークアップになります:

<form action="/search" method="get">
  <label for="q">Search for:</label>
  <input id="q" name="q" type="text" />
  <input name="commit" type="submit" value="Search" />
</form>

text_field_tag と submit_tag に加えて、 HTML 内のすべてのフォームコントロールのための、同様のヘルパーがあります。

全てのフォームの入力では、 ID 属性は、その名前から生成されます。(例では "q" )
これらの ID は、 CSS でのスタイリングまたは JavaScript でのフォームコントロールの操作、に非常に役立ちます。

1.2 フォームヘルパ呼び出し中の複数のハッシュ(Multiple Hashes in Form Helper Calls)

今では form_tag ヘルパは2つの引数を受け取ることを見ました:アクションのパスと、オプションのハッシュです。
このハッシュは、送信フォームのメソッドとフォーム要素のクラス等の HTML オプションを、指定します。

link_to ヘルパと同様に、パス引数は必ずしも文字列を指定される必要はありません。
URL パラメータのハッシュは、 Rails のルーティング機構が、有効な URL にするでしょう。
しかしながら、これはメソッドの引数として複数のハッシュを渡すための悪い方法です:

form_tag(:controller => "people", :action => "search", :method => "get", :class => "nifty_form")
# => <form action="/people/search?method=get&class=nifty_form" method="post">

ここで、二つのハッシュを渡したいが、 Ruby インタプリタは一つのハッシュしか見ていません。
ので、 Rails は無関係なパラメータを含む URL を構築するでしょう。
引数として複数のハッシュを渡す正しい方法は、最初のハッシュ(または両方のハッシュ)を中括弧で区切ることです:

form_tag({:controller => "people", :action => "search"}, :method => "get", :class => "nifty_form")
# => <form action="/people/search" method="get" class="nifty_form">

これは、フォームヘルパーを使用する上でよくある落とし穴で、それら多くは複数のハッシュを受け入れるからです。
だから今後、ヘルパーが予期しない出力を生成した場合、ハッシュパラメータを正しく区切っていることを確認して下さい。

最初のハッシュを区切ること無しに、第二のハッシュの区切らないで下さい。
そうしないと、メソッドの呼び出しが expecting tASSOC syntax error(訳注:tASSOCは => のこと)になります。

1.3 フォーム要素を生成するためのヘルパ(Helpers for Generating Form Elements)

Rails は、チェックボックス、テキストフィールド、ラジオボタンのような
フォーム要素を生成するための一連のヘルパーを提供しています。
これらの、 text_field_tag 、 check_box_tag 等の _tag で終わる名前の基本的なヘルパは、一つの <input> 要素だけを生成します。
これらの最初のパラメータは、常にその入力の name です。
コントローラー内では、この name は、ユーザーによって入力された値の取得に使用される params ハッシュ内のキーです。
例えば、フォームが以下を含む場合、

<%= text_field_tag(:query) %>

コントローラーのコードが、ユーザーによって入力された値の検索するのに使用するべきです。

params[:query]

入力を名付ける時、値が params ハッシュのトップレベルなのか、配列やネストしたハッシュの内側なのか
を制御する特定の規則を、 Rails が使用することに注意してください。
parameter_names セクション内でそれらについての詳細を読むことができます。
これらのヘルパーの正確な使い方の詳細については、APIドキュメントを参照してください。

1.3.1 チェックボックス

チェックボックスは、ユーザーに有効または無効に出来るオプションのセットを与えるフォームコントロールです:

<%= check_box_tag(:pet_dog) %>
  <%= label_tag(:pet_dog, "I own a dog") %>
<%= check_box_tag(:pet_cat) %>
  <%= label_tag(:pet_cat, "I own a cat") %>

出力:

<input id="pet_dog" name="pet_dog" type="checkbox" value="1" />
  <label for="pet_dog">I own a dog</label>
<input id="pet_cat" name="pet_cat" type="checkbox" value="1" />
  <label for="pet_cat">I own a cat</label>

check_box_tag の2番目のパラメータは、入力の value です。
チェックボックスがチェックされている場合、これはブラウザによって送信される値です。
(すなわち、その値は params ハッシュ内に存在するでしょう)
上記のフォームで、ユーザーが所有しているペットを確認するために
params[:pet_dog] と params[:pet_cat] をチェックすべきでしょう。

1.3.2 ラジオボタン

ラジオボタンは、チェックボックスに似ていますが、
相互に排他的なオプションのセットを指定するためのコントロールです。
(つまりユーザーは一つだけを選ぶことが出来ます):

<%= radio_button_tag(:age, "child") %>
  <%= label_tag(:age_child, "I am younger than 21") %>
<%= radio_button_tag(:age, "adult") %>
  <%= label_tag(:age_adult, "I'm over 21") %>

出力:

<input id="age_child" name="age" type="radio" value="child" />
  <label for="age_child">I am younger than 21</label>
<input id="age_adult" name="age" type="radio" value="adult" />
  <label for="age_adult">I'm over 21</label>

radio_button_tag の2番目のパラメータは、 check_box_tag と同様に、入力の value です。
これらの2つのラジオボタンは同じ名前 ( age ) を共有しているので、ユーザーは1つだけしか選択できず、
params[:age] は "child" または "adult" を格納しているでしょう。

常に、チェックボックスとラジオボタン全てにラベルを使用して下さい。
特定のオプションとテキストを関連付け、大きなクリック可能領域を提供します。

1.4 興味深いその他のヘルパ(Other Helpers of Interest)

特筆すべきその他のフォームコントロールは、テキストエリア、パスワード入力、隠し入力です:

<%= text_area_tag(:message, "Hi, nice site", :size => "24x6") %>
<%= password_field_tag(:password) %>
<%= hidden_field_tag(:parent_id, "5") %>

出力:

<textarea id="message" name="message" cols="24" rows="6">Hi, nice site</textarea>
<input id="password" name="password" type="password" />
<input id="parent_id" name="parent_id" type="hidden" value="5" />

隠し入力はユーザーに表示されませんが、任意のテキスト入力のようなデータを保持します。
それらの値は JavaScript で変更することができます。

(任意の目的のために)パスワードの入力フィールドを使用している場合
ApplicationController 内で filter_parameter_logging(:password) を有効にすることにより、
アプリケーションのログの中でその値が表示されるのを阻止できます。

2 モデルオブジェクトの処理(Dealing with Model Objects)

2.1 モデルオブジェクトのヘルパ(Model Object Helpers)

フォームの特に一般的なタスクは、モデルオブジェクトを編集することや作成することです。
その *_tag ヘルパは、確かにこのタスクに使用されますが、一方で、
正しいパラメータ名が使用されて、適切な入力のデフォルト値を設定していることを
あなたが確認しなければならない各タグにとっては冗長です。
Rails はヘルパーをこのタスクに合わせて提供しています。
これらのヘルパは、お尻に _tag がありません。例えば、 text_field 、 text_area です。

これらのヘルパについて、最初の引数はインスタンス変数の名前で、
2番目の引数はオブジェクトを呼び出すメソッドの名前(通常は属性)です。
Rails はオブジェクトのメソッドの戻り値をコントロールする入力の value を設定し、適切な入力の name を設定するでしょう。
コントローラは、 @person を定義していて、その name が Henry なら、フォームが以下を含み:

<%= text_field(:person, :name) %>

は、以下のような出力を生成するでしょう。

<input id="person_name" name="person[name]" type="text" value="Henry"/>

上のフォーム送信で、ユーザーによって入力された値は、 params[:person][:name] 内に格納されるでしょう。
params[:person] ハッシュは、 Person.new か、 @person が Person のインスタンスである場合の、 @person.update_attributes に渡すのに適しているでしょう。
属性の名前は、最も一般的なこれらのヘルパーの2番目のパラメータですが、これは強制ではありません。
上記の例では、 person オブジェクトが name や name= メソッドを持っている限り、 Rails は幸せでしょう。

モデルオブジェクトの実際のインスタンスでは無く、
:person や "person" のようなインスタンス変数の名前を渡す必要があります。

Rails は、モデルオブジェクトに関連付いたバリデーションエラーを表示するためのヘルパーを提供します。
これらの詳細は Active Record Validations and Callbacks で解説されています。

2.2 オブジェクトへのフォームのバインド(Binding a Form to an Object)

快適さは増しているとはいえ、完璧にはほど遠いです。
Person が編集するための多くの属性を持っているなら、編集されたオブジェクトの名前を何度も繰り返すことになります。
私たちがしたいと思うことはモデルオブジェクトにフォームをバインドすることであり、これまさに form_for がします。

記事を扱うコントローラー app/controllers/articles_controller.rb があると仮定すると:

def new
  @article = Article.new
end

対応するビュー、 app/views/articles/new.html.erb はこのように form_for を使っています。

<%= form_for :article, @article, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :body, :size => "60x12" %>
  <%= submit_tag "Create" %>
<% end %>

いくつかの注意があります:

  1. :article はモデルの名前で、 @article は編集された実際のオブジェクト
  2. オプションの単一のハッシュがあります。ルーティングオプションは :url ハッシュに、 HTML オプションは :html ハッシュに渡されます。
  3. form_for メソッドはフォームビルダオブジェクトを yield します( f 変数 )
  4. フォームコントロールを作成するためのメソッドはフォームビルダオブジェクトの f で呼び出されます。

結果の HTML は:

<form action="/articles/create" method="post" class="nifty_form">
  <input id="article_title" name="article[title]" size="30" type="text" />
  <textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
  <input name="commit" type="submit" value="Create" />
</form>

form_for に渡された名前は、フォームの値にアクセスするための params 内で使われるキーをコントロールします。
ここで名前は article で、全ての入力は article[attribute_name] というフォームの name を持っています。
従って、 create アクション内の params[:article] は、 :title と :body のキーを持つハッシュでしょう。
parameter_names セクションで、入力名の重要性について更に読むことが出来ます。

フォームビルダ上で呼ばれたヘルパーメソッドは、編集されたオブジェクトを除いて、モデルオブジェクトヘルパと同一です。
既にフォームビルダによって管理されているので、指定する必要はありません

実際に <form> タグを作ることなく、 fields_for ヘルパーで同様のバインディングを作成することができます。
追加のモデルオブジェクトを同じフォームで編集するのに便利です。
例えば、 ContactDetail モデルと関連付けられている Person モデルがあった場合、
このように、両方のフォームを作れます:

<%= form_for :person, @person, :url => { :action => "create" } do |person_form| %>
  <%= person_form.text_field :name %>
  <%= fields_for @person.contact_detail do |contact_details_form| %>
    <%= contact_details_form.text_field :phone_number %>
  <% end %>
<% end %>

次の出力を生成します:

<form action="/people/create" class="new_person" id="new_person" method="post">
  <input id="person_name" name="person[name]" size="30" type="text" />
  <input id="contact_detail_phone_number" name="contact_detail[phone_number]" size="30" type="text" />
</form>

fields_for によって yield されているオブジェクトは、form_for によって yield されているオブジェクトのようなフォームビルダです。
(実際、内部で、 form_for は fields_for を呼び出しています)

2.3 レコード識別の依存(Relying on Record Identification)

Article モデルはアプリケーションのユーザーが直接利用できます - 続く Rails で開発するためのベストプラクティス -
リソースとして宣言する必要があります。

map.resources :articles

リソースを宣言することは、副作用があります。
リソースの設定と利用についての更なる情報は Rails Routing From the Outside In を読んで下さい。

RESTful なリソースを扱う時、レコード識別に依存しているなら、 form_for の呼び出しが大幅に容易に得ることができます。
要するに、モデルのインスタンスを渡すだけで、 Rails がモデル名と残りの部分を把握できます:

## 新しい記事の作成
# 長いスタイル:
form_for(:article, @article, :url => articles_path)
# 同じ, 短いスタイル (レコード識別の利用):
form_for(@article)

## 既存の記事の編集
# 長いスタイル:
form_for(:article, @article, :url => article_path(@article), :html => { :method => "put" })
# 短いスタイル:
form_for(@article)

短いスタイルの form_for の呼び出し方は、レコードを新しく作成する場合、既存の場合に関わらず、同様で、
便利なことに注意して下さい。
レコード識別は、 record.new_record? に問い合わせることによって、レコードが新しいかどうか考え出すのに充分賢いです。
また、 submit のための正しいパス、オブジェクトのクラスに基づいた名前を選択します。

Rails はまた自動的で適切に、フォームの class と id を設定します:
フォームが作成した article は id と new_article という classを持っています。
id が 23 の article を編集するなら、class は edit_article 、 id は edit_article_23 に設定されます。
このガイドの残りの部分では、簡潔のためにこれらの属性は省略されます。

モデル内で STI (単一テーブル継承)を使う時、親クラスがリソース宣言されている場合のみレコード識別を使うことが出来せん。
モデル名、 :url 、 :method を明示的に指定する必要があります

2.3.1 名前空間の処理

名前空間のルートを作成した場合、 form_for には気の利いた省略があります。
アプリケーションが、 admin 名前空間を持っている場合

form_for [:admin, @article]

admin 名前空間内の articles controller に送信するフォームを作成するでしょう。
(update の場合 admin_article_path(@article) に送信します)
名前空間にレベルがいくつかある場合も、構文は似ています:

form_for [:admin, :management, @article]

Rails のルーティングシステムの詳細、関連する規則については、 routing guide を見てください。

2.4 PUT や DELETE メソッドとフォームがどのように働くか?(How do forms with PUT or DELETE methods work?)

Rails フレームワークは、アプリケーションの RESTful 設計を奨励し、
多くの( "GET" 、 "POST" 以外の) "PUT" 、 "DELETE" リクエスト作るだろうことを意味します。
しかしながら、ほとんどのブラウザでは、フォームを送信するとき、 "GET" と" POST" メソッド以外のサポートしていません。

Rails は、目的のメソッドを反映するために設定された _method という名前の隠し入力を、
POST を通して他のメソッドをエミュレートすることによって、この問題を回避します。

form_tag(search_path, :method => "put")

出力:

<form action="/search" method="post">
  <div style="margin:0;padding:0">
    <input name="_method" type="hidden" value="put" />
    <input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
  </div>
...

POST されたデータを解析する時、 HTTP メソッドが内部で指定されたなら(この例では "PUT" )
Rails は特別な _method パラメータを考慮し、そのように振る舞います。

3 簡単にセレクトボックスを作る(Making Select Boxes with Ease)

HTML 内のセレクトボックスは、かなりの量のマークアップ(選択するための各オプションごとに1つのオプション要素)を必要とし、
従って、動的に生成することが最も理に叶っています。

マークアップはこのようになります:

<select name="city_id" id="city_id">
  <option value="1">Lisbon</option>
  <option value="2">Madrid</option>
  ...
  <option value="12">Berlin</option>
</select>

ここでは、ユーザーに提示される名前の都市のリストがあります。
内部アプリケーションはその ID だけを処理したいので、オプションの value の属性として使用されてます。
Rails がどうやって助けてくれるか見てみましょう。

3.1 select と option タグ(The Select and Option Tags)

最も一般的なヘルパーは、 select_tag で - その名称が示すように - 単に
オプションの文字列をカプセル化した SELECT タグを生成します。

<%= select_tag(:city_id, '<option value="1">Lisbon</option>...') %>

これがスタートですが、動的にオプションのタグが作成されません。
options_for_select ヘルパーによって option タグを生成することができます:

<%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...]) %>

出力:

<option value="1">Lisbon</option>
<option value="2">Madrid</option>
...

options_for_select の最初の引数はネストされた配列です。
その各要素は2つの要素を持っています: option のテキスト(都市名)と option のvalue(都市 id )。
option の value はコントローラに送信されるものです。
多くの場合、これはデータベースオブジェクトに対応する id ですが、この場合は必要はありません。

これを知っている場合は、望みを達成するために select_tag と options_for_select を組み合わせることができます。
完全なマークアップは:

<%= select_tag(:city_id, options_for_select(...)) %>

options_for_select は値を渡すことによって、オプションを事前に選んでおけます。

<%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...], 2) %> 

出力:

<option value="1">Lisbon</option>
<option value="2" selected="selected">Madrid</option>
... 

Rails はその option の内部 value がこの値にマッチするものを生成したのを見つけたら、オプションに selected 属性を追加します。

options_for_select の2番目の引数は、正確に希望する内部の value に等しくなければなりません。
特に、 値が整数 2 の場合、 "2" を options_for_select に渡すことはできません -- 2 を渡さなければなりません。
すべて文字列として params ハッシュから抽出された値に注意して下さい。

3.2 モデルを処理するセレクトボックス(Select Boxes for Dealing with Models)

ほとんどの場合、フォームコントロールは、特定のデータベースモデルに縛られるので、
Rails が目的に応じたヘルパを提供していると期待するかもしれません。
他のフォームヘルパーとの一貫性から、モデルを扱う時 select_tag から _tag サフィックスを削除します。

# controller:
@person = Person.new(:city_id => 2)
# view:
<%= select(:person, :city_id, [['Lisbon', 1], ['Madrid', 2], ...]) %> 

三番目のパラメータ、オプションの配列、は options_for_select に渡したのと同じ種類の引数であることに注意して下さい。
1つの利点は、ここでユーザーが既に持っている場合は、正しい都市を事前選択することについて心配する必要はないことです。
Rails はこれを @person.city_id 属性から読み取り、これを行います。

他のヘルパーと同様に、 @person オブジェクトのスコープのフォームビルダー上の select ヘルパーを使用した場合、構文はこうなります:

# select on a form builder
<%= f.select(:city_id, ...) %>

belongs_to アソシエーションを設定するために、 select (もしくは collection_select 、 select_tag のような類似したヘルパ)を使っている場合、
アソシエーション自身の名前ではなく、外部キーの名前(上記の例では city_id )を渡す必要があります。
city_id の代わりに city を指定した場合、 Person.new か update_attributes に params ハッシュを渡したら、
Active Record は、 ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) エラーを起こすでしょう。
この別の方法は、フォームヘルパが属性を編集するだけです。
ユーザーが直接外部キーを編集することができることの潜在的なセキュリティの影響を認識する必要もあります。
attr_protected と attr_accessible の使用を検討すべきです。
これについて詳細については、 Ruby On Rails Security Guide を見てください。

3.3 任意のオブジェクトのコレクションからオプションタグ(Option Tags from a Collection of Arbitrary Objects)

options_for_select が生成したオプションのタグは、あなたが各オプションのためにテキストと値を含む配列を作成することを、必要とします。
しかし、(おそらく Active Record の) City モデルがあって、
それらのオブジェクトのコレクションから option タグを生成したいとしたらどうでしょうか?
1つのソリューションは、それらの反復でネストされた配列を作成することでしょう:

<% cities_array = City.all.map { |city| [city.name, city.id] } %>
<%= options_for_select(cities_array) %> 

これは完全に有効なソリューションですが、 options_from_collection_for_select の冗長な代替です。
このヘルパーは任意のオブジェクトのコレクションと2つの追加引数:
option の valuetext それぞれを読み込むメソッドの名前、を期待します。

<%= options_from_collection_for_select(City.all, :id, :name) %>

名前が示すとおり、これは option タグを生成するだけです。
動作するセレクトボックスを生成するには、 options_for_select と同じように select_tag と組み合わせて使用する必要があります。
モデルオブジェクトが動作している時、 select は select_tag と options_for_select を組み合わせ、
collection_select は options_from_collection_for_select と select_tag を組み合わせます。

<%= collection_select(:person, :city_id, City.all, :id, :name) %>

要約すると、 options_for_select が select のための用途なのと同じように、
options_from_collection_for_select は、 collection_select のための用途です。

options_for_select に渡されるペアは、1番目に name と2番目に id を持っているべきです。
しかしながら、 options_from_collection_for_select では、最初の引数は value メソッド、二番目は text メソッドです。

3.4 タイムゾーンと国の選択(Time Zone and Country Select)

Rails がサポートしているタイムゾーンを活用するには、どのようなタイムゾーンはいるかユーザーに尋ねる必要があります。
そうすることは、 collection_select を使用する事前定義された TimeZone オブジェクトのリストから
select option を生成することを必要とするでしょう。
ですが、単に、既にこれをラップしている time_zone_select ヘルパーを使用することができます:

<%= time_zone_select(:person, :time_zone) %>

また、これをするもっと手動(したがって、よりカスタマイズ可能)の方法として、 time_zone_options_for_select ヘルパーがあります。
これらの2つのメソッドの可能な引数について学ぶために API ドキュメントをご覧ください。

Rails は国を選択するために country_select ヘルパーを使いますが、
これは country_select plugin に抽出されています。
これを使う時は、リストから特定の名前を除外したり追加したりすることは、物議を醸しだすかもしれないことに注意して下さい。
(この機能が Rails から抽出された理由です。)

4 日付と時刻のフォームヘルパーの使用(Using Date and Time Form Helpers)

日付と時刻のヘルパーは、2つの重要な点で他のすべてのフォームヘルパーとは異なります:

  1. 日付と時刻は単一の input 要素の表現ではありません。
    代わりに複数持ち、1つのコンポーネント(年、月、日、等)ごとなので、
    params ハッシュの中に日付または時間を表す単一の値はありません。
  2. 他のヘルパは、ヘルパは必要最小限のヘルパかモデルオブジェクト上で動作するヘルパか示すために _tag 接尾辞を使います。
    日付と時刻では、 select_date 、 select_time 、 select_datetime は飾り気のないヘルパで、
    date_select 、 time_select 、 datetime_select は、モデルオブジェクトヘルパと同等です。

これら両方のヘルパーファミリは、様々なコンポーネント(年、月、日、等)のための一連のセレクトボックスを作ります。

4.1 ヘルパーの要点(Barebones Helpers)

select_* ヘルパファミリーは、 Date 、 Time 、 DateTime のインスタンスを第一引数としてとり、
現在の選択されている値として使用します。
このパラメータを省略する場合、現在の日付が使用されます。
例えば:

<%= select_date Date.today, :prefix => :start_date %>

出力(簡潔にするため省略された実際のオプションの値)

<select id="start_date_year" name="start_date[year]"> ... </select>
<select id="start_date_month" name="start_date[month]"> ... </select>
<select id="start_date_day" name="start_date[day]"> ... </select>

上記入力は、 :year 、 :month 、 :day がキーのハッシュである params[:start_date] 内に結果を出します。
実際の Time か Date オブジェクトを取得するために、これらの値を抽出し、適切なコンストラクタに渡す必要があるでしょう。
例えば:

Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)

:prefix オプションは、 params ハッシュから日付コンポーネントのハッシュを取得するために使用されるキーです。
ここでは start_date を設定します。省略された場合 date がデフォルトになります。

4.2 モデルオブジェクトヘルパ(Model Object Helpers)

Active Record は、 params ハッシュの全ての要素が一つの属性に対応すると期待するので、
select_date は Active Record オブジェクトを update か create するフォームではうまく動きません。
日付と時刻のモデルオブジェクトのヘルパーは、特別な名前のパラメータを送信します、
Active Record がそのような名前のパラメータを見たときに、
他のパラメータと組み合わせ、コンストラクタに適切なカラム型を与える必要があるということを知っています。
例えば:

<%= date_select :person, :birth_date %>

出力(簡潔にするため省略された実際のオプションの値)

<select id="person_birth_date_1i" name="person[birth_date(1i)]"> ... </select>
<select id="person_birth_date_2i" name="person[birth_date(2i)]"> ... </select>
<select id="person_birth_date_3i" name="person[birth_date(3i)]"> ... </select>

params ハッシュ内の結果は

{:person => {'birth_date(1i)' => '2008', 'birth_date(2i)' => '11', 'birth_date(3i)' => '22'}}

これが Person.new (か update_attributes )に渡された時、 Active Record は
これらのパラメータは、すべての birth_date の属性を構築するために使用する必要があることを見極め、
Date.civil のような関数にこれらのパラメータをどの順番で渡すべきか決定するために接尾辞の情報を使います。

4.3 一般的なオプション(Common Options)

ヘルパーの両方のファミリーが、独立した select タグを生成する関数の同じコアセットを使い、両方ほぼ同じオプションを受け入れます。
特に、デフォルトでは Rails は、現在の年の両サイドに5つオプションを生成します。
適切な範囲では無い場合、 :start_year と :end_year オプションはこれをオーバーライドします。
利用可能なオプションの完全なリストについては API documentation を参照して下さい。

経験則としては、モデルオブジェクトで動いてる場合は、 date_select を使用すべきで、
結果を日付でフィルタする検索フォームのような、その他の場合は、 select_date を使用すべきです。

多くの場合、組み込みの日付ピッカーは、日付と曜日の間の関係を算出するのを支援しないため、使いにくいです。

4.4 個々のコンポーネント(Individual Components)

時折、年や月等、単一の日付コンポーネントだけを表示したいでしょう。
Rails は、このためにヘルパーのシリーズを提供しています。
各コンポーネントに一つずつ、 select_year 、 select_month 、 select_day 、 select_hour 、 select_minute 、 select_second があります。
これらのヘルパーはかなり簡単です。
デフォルトでは、これらのヘルパは時間のコンポーネントにちなんで名付けられた入力フィールドを生成するでしょう。
(例えば、 select_year のための "year" 、 select_month のための "month" )
ですが、これは :field_name オプションでオーバーライドすることができます。
:prefix オプションは、 select_date や select_time と同様に動き、同様のデフォルト値を持っています。

最初のパラメータはどの値が選択されるべきかを指定するでしょう。
また Date 、 Time 、 DateTime どのインスタンスでも可能で、その場合、関連するコンポーネントが抽出されるでしょう。
または数値も可能です。
例えば:

<%= select_year(2009) %>
<%= select_year(Time.now) %> 

は、現在の年が 2009 年なら同じ出力を生成します。
またユーザーによって選ばれた値は params[:date][:year] で取得できます。

5 ファイルのアップロード(Uploading Files)

一般的なタスクは、人の写真や、処理するためのデータを格納している CSV ファイルであろうとなかろうと、
多少のファイルをアップロードすることです。
ファイルのアップロードに関して覚えておく最も大事なことは、
フォームのエンコードは必ず "multipart/form-data" に設定しなければいけません。
これをするのを忘れた場合、ファイルはアップロードされないでしょう。
HTML オプションとして、 :multi_part => true を渡すことによって、出来ます。
これはつまり form_tag の場合、2番目のオプションのハッシュに、
form_for の場合、 :html のハッシュの内部に渡される必要があります。

続く二つのフォームはどちらもファイルをアップロードします。

<%= form_tag({:action => :upload}, :multipart => true) do %>
  <%= file_field_tag 'picture' %>
<% end %>

<%= form_for @person, :html => {:multipart => true} do |f| %>
  <%= f.file_field :picture %>
<% end %>

Rails はヘルパーの通常のペアを提供しています:飾り気のない file_field_tag とモデル指向の file_field です。
他のヘルパーとの唯一の違いは、何の意味もないので、ファイルの入力のデフォルト値を設定出来ません。
予想通り、最初のケースではアップロードしたファイルは params[:picture] に、
二番目のケースでは params[:person][:picture] に入っています。

5.1 アップロードされたものの取得(What Gets Uploaded)

params ハッシュ内のオブジェクトは IO のサブクラスのインスタンスです。
アップロードしたファイルのサイズに応じて、実際に StringIO になるか、テンポラリファイルから返された File のインスタンスになります。
どちらの場合も、オブジェクトは、ユーザーコンピューター上でファイルが持っていた名前を含む original_filename 属性と
アップロードしたファイルの MIME タイプを含む content_type 属性を持っているでしょう。
次のスニペットは、アップロードされたコンテンツを、 #{Rails.root}/public/uploads に、元のファイルと同じ名前で保存します。
(フォームは前の例の一つだと仮定します)

def upload
  uploaded_io = params[:person][:picture]
  File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
    file.write(uploaded_io.read)
  end
end

いったんファイルがアップロードされると、潜在的なタスクが沢山あり、
ファイルをどこに保存するか(ディスク上、 Amazon S3 等)、
モデルとリサイズした画像ファイルの関連付け、サムネイルの生成等です。
この複雑さは、このガイドの範囲を超えていますが、これらを支援するために設計されているプラグインもあります。
2つのよく知られたものは、 Attachment-FuPaperclip です。

ユーザーがファイルを選択していない場合、対応するパラメータは空の文字列になります。

5.2 Ajaxでの処理(Dealing with Ajax)

他のフォームとは異なり、非同期のファイルのアップロードフォームを作ることは、
form_for と remote_form_for を置き換えるほど単純ではありません。
Ajax フォームで、ブラウザ内で実行された JavaScript によって、シリアル化は行われて、
JavaScript は、ハードドライブからファイルを読み取ることができないので、ファイルはアップロードできません。
最も一般的な回避策は、 フォームの送信のターゲットとして目に見えない iframe を使用します。

6 フォームビルダのカスタマイズ(Customising Form Builders)

前述のように、 form_for と fields_for によって yield されたオブジェクトは
フォームビルダー(またはそのサブクラス)のインスタンスです。
フォームビルダーは、単一のオブジェクトのフォーム要素を表示するという概念をカプセル化します。
通常の方法でフォームのためのヘルパを書くことがもちろんでき、
フォームビルダをサブクラス化し、ヘルパを追加することもできます。

<%= form_for @person do |f| %>
  <%= text_field_with_label f, :first_name %>
<% end %>

は、以下で置き換えられます。

<%= form_for @person, :builder => LabellingFormBuilder do |f| %>
  <%= f.text_field :first_name %>
<% end %>

LabellingFormBuilder クラスを次のように定義することによって:

class LabellingFormBuilder < ActionView::Helpers::FormBuilder
  def text_field(attribute, options={})
    label(attribute) + super
  end
end

頻繁に再利用する場合、 :builder => LabellingFormBuilder オプションを自動的に適用する
labeled_form_for ヘルパーを定義できます。

フォームビルダーは、以下のことをしたとき、何が起こるか決定するために使います

<%= render :partial => f %>

f が FormBuilder のインスタンスであるなら、これはフォームパーシャルをレンダリングし、
フォームビルダにパーシャルのオブジェクトを設定するでしょう。
フォームビルダーが LabellingFormBuilder クラスの場合は
labelling_form パーシャルが代わりにレンダリングされるでしょう。

7 パラメータの命名規則について理解する(Understanding Parameter Naming Conventions)

前のセクションで見てきたように、
フォームからの値は、 params ハッシュのトップレベルか、別のハッシュのネストです。
Person モデルの標準的な create アクションの例では、
params[:model] は通常、 person を作成するための全ての属性のハッシュです。
params ハッシュはまた、配列やハッシュの配列を含みます。

根本的に、 HTML フォームは、構造化データの並べ替えについては知らず、
生成する全ては name-value のペアで、そのペアはただの文字列です。
アプリケーション内で見る配列とハッシュは、 Rails が使っている命名規約の結果です。

Rails のパラメータパーサーを直接呼び出すためにコンソールを使うことによって、
このセクションの例を素早く試せるだろうことに気づくかもしれません。
例えば

ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789"
  # => {"name"=>"fred", "phone"=>"0123456789"}

7.1 基本的な構造(Basic Structures)

2つの基本的な構造は、配列とハッシュです。
ハッシュは、 params 内の値にアクセスするために使われた構文を反映しています。
例えば、フォームが以下含む場合、

<input id="person_name" name="person[name]" type="text" value="Henry"/>

params ハッシュは、以下を含むでしょう。

{'person' => {'name' => 'Henry'} }

また params[:person][:name] はコントローラー内で送信された値を取得するでしょう。

ハッシュは、必要なだけのレベルのネストができます、例えば:

<input id="person_address_city" name="person[address][city]" type="text" value="New York"/>

params ハッシュ内の結果は

{'person' => {'address' => {'city' => 'New York'} } }

通常 Rails は、重複しているパラメータ名を無視します。
パラメータ名が角かっこ [] の空のセットが含む場合、それらは配列に蓄積されます。
複数の電話番号を入力できるようにしたい場合、フォームにこれを置くことができます:

<input name="person[phone_number][]" type="text"/>
<input name="person[phone_number][]" type="text"/>
<input name="person[phone_number][]" type="text"/>

この結果は、 params[:person][:phone_number] に配列で格納されます。

7.2 それらの合成(Combining Them)

これら二つの概念を混ぜあわせ、マッチさせることができます。
例えば、ハッシュの一つの要素は、上記の中のように配列かもしれないし、ハッシュの配列を持つこともできます。
例えば、 以下のフォームの断片を繰り返すことによって、任意の数のアドレスを作成できるようになるでしょう。

<input name="addresses[][line1]" type="text"/>
<input name="addresses[][line2]" type="text"/>
<input name="addresses[][city]" type="text"/>

これは params[:addresses] 内に、 line1 、 line2 、 city をキーに持つ、ハッシュの配列が結果入るでしょう。
Rails は、既に現在のハッシュに存在する入力名を検出するたびに
新しいハッシュの中に、値を蓄積し始めることを決定します。

制限はありません、しかしながら、ハッシュは任意のネストにできますが、 "配列" は1レベルだけ許されます。
配列は、通常、ハッシュで置き換えることができます、例えば、
モデルオブジェクトの配列を一つ持つ代わりに、 id がキーのモデルオブジェクトのハッシュ、配列のインデックスやその他のパラメータを持つことができます。

配列のパラメータは check_box ヘルパでは上手く動きません。
HTML の仕様によると、チェックボックスは値を送信しません。
しかしながら、チェックボックスが常に値を送信することは、とても便利です。
check_box ヘルパは同じ名前を持つ補助の隠し入力を作成し、これを偽装します。
チェックボックスがオフになっている場合、隠し入力だけ送信され、
チェックされている場合、両方が送信されますが、チェックボックスにより送信された値が優先されます。
配列内のパラメータを操作する時、重複した入力名は、いつ新しい配列要素を始めるかをどうやって決めるかわからないので、この重複した送信は Rails を混乱させます。
check_box_tag を使うか配列の代わりにハッシュを使うか、どちらかが望ましいです。

7.3 フォームヘルパーの利用(Using Form Helpers)

前のセクションでは、 Rails のフォームヘルパを全く使いませんでした。
自身で入力名を作ること、それらを直接 text_field_tag のようなヘルパーに渡すことができ、
Rails はまたより高いレベルのサポートを提供します。
自由に使える二つのツールがあります。
form_for と fields_for への名前パラメータと、ヘルパが受け取る :index オプションです。

person の address のそれぞれについて、 edit フィールドのセットがあるフォームをレンダリングしたいかもしれません。

<%= form_for @person do |person_form| %>
  <%= person_form.text_field :name %>
  <% for address in @person.addresses %>
    <%= person_form.fields_for address, :index => address do |address_form|%>
      <%= address_form.text_field :city %>
    <% end %>
  <% end %>
<% end %>

person が id 23 と 45 の二つの address を持っていると仮定すると、このような出力が出来ます:

<form action="/people/1" class="edit_person" id="edit_person_1" method="post">
  <input id="person_name" name="person[name]" size="30" type="text" />
  <input id="person_address_23_city" name="person[address][23][city]" size="30" type="text" />
  <input id="person_address_45_city" name="person[address][45][city]" size="30" type="text" />
</form>

params ハッシュ内の結果は

{'person' => {'name' => 'Bob', 'address' => { '23' => {'city' => 'Paris'}, '45' => {'city' => 'London'} } } }

最初のフォームビルダ上で fields_for を呼んだので、 Rails は、これらすべての入力は person ハッシュの一部だと知っています。
:index オプションを指定することにより、入力を person[address][city] と名付ける代わりに、
address と city の間に、 [] によって囲まれた index が挿入されるべきだと、 Railsに 伝えています。
このように Active Record オブジェクトを渡す場合、 Rails はその上で to_param を呼び、
それはデフォルトでデータベースの id を返すでしょう。
Address レコードが変更されるべき時に見つけるのが簡単になり、しばしば役に立ちます。
数値を、他の重要な、文字列や、 nil すら(配列のパラメータ内で作成された結果)と共に、渡すことができます。

より複雑な入れ子を作成するために、入力名の最初の部分(上記例では person[address] )を明示的に指定することが出来ます。
例えば:

<%= fields_for 'person[address][primary]', address, :index => address do |address_form| %>
  <%= address_form.text_field :city %>
<% end %>

は、このような入力を作ります。

<input id="person_address_primary_1_city" name="person[address][primary][1][city]" size="30" type="text" value="bologna" />

一般的なルールとして、最終的な入力名は fields_for/form_for に渡された名前と index の値と属性の name を連結したものです。
text_field のようなヘルパに :index オプションを直接渡すこともまた出来ます。
が、通常、独立した入力コントロール上ではなく、フォームビルダレベルで指定するほうが繰り返しが少ないです。

ショートカットとして name[] を追加して、 :index オプションを省くことが出来ます。
これは :index => address を指定するのと同じです

<%= fields_for 'person[address][primary][]', address do |address_form| %>  <%= address_form.text_field :city %> <% end %>

前の例とまったく同じ出力を生成します。

8 複雑なフォームの構築(Building Complex Forms)

多くのアプリケーションは、1つのオブジェクトを編集する単純なフォームを超えて成長します。
例えば、 Person を作成するとき、(同じフォーム上で)複数のアドレスレコード(自宅、職場、他)を作成することをユーザーに許可したいかもしれません。
person を編集した後、ユーザーは必要に応じて追加、削除、修正できるべきです。
このガイド内の、これを処理するのに必要な断片の全てから見るに、
Rails はまだこれを達成するための標準的なエンドツーエンドの方法を持っていませんが、
しかし、多くの可能なアプローチが出ています。
これらを含みます:

9 Changelog

Lighthouse ticket

  • April 6, 2010: Fixed document to validate XHTML 1.0 Strict. Jaime Iniesta

10 Authors

コメント欄(誤訳・誤字があれば教えて頂ければ幸いです。)