こんにちは、hachi8833です。
Rails 3のform_for
メソッドのAPIドキュメントをすべて翻訳いたしました。
Rails 4および5のform_for
メソッドのAPIドキュメント翻訳については以下をご覧ください。
概要
Rails 3、4、5のform_for
メソッドを最新の公式APIドキュメントでチェックしてみたところ、現時点でのRails 4とRails 5向けform_for
メソッドのAPIドキュメントは完全に一致していました。また、Rails 3とRails 4/5のドキュメントの差分もさほどありませんでした。
- APIドキュメント: form_for: Rails 3.2.22.5
なお、form_for
とform_tag
は今後form_with
で一元的に利用できるようになるとのことです。
form_for
(Rails 3)
#API呼び出し(Rails 3、4、5共通)
form_for(record, options = {}, &block)
フィールドの値をユーザーに問い合わせるための特定のモデルオブジェクトを元に、フォームとスコープを作成します。
Railsのform_for
を以下のように使って、簡潔な「リソース指向フォーム」を生成できます。
<%= form_for @offer do |f| %>
<%= f.label :version, 'Version' %>:
<%= f.text_field :version %><br />
<%= f.label :author, 'Author' %>:
<%= f.text_field :author %><br />
<%= f.submit %>
<% end %>
form_for
は、レコードのイントロスペクションに基づいたRESTfulなフォームパラメータを生成できます。しかし、この動作を理解するにはform_for
の基本となる別の一般的な用法についてまず知っておく必要があります。
一般的な#form_for
form_for
を一般的な方法で呼び出すと、モデルについてのフォームビルダが生成されます。
<%= form_for :person do |f| %>
First name: <%= f.text_field :first_name %><br />
Last name : <%= f.text_field :last_name %><br />
Biography : <%= f.text_area :biography %><br />
Admin? : <%= f.check_box :admin %><br />
<%= f.submit %>
<% end %>
引数には、フォームで使うオブジェクトの名前をシンボルか文字列で指定します。
フォームビルダは、モデルを何らかの形で実行する通常のフォームヘルパとして動作します。
<%= f.text_field :first_name %>
上のコードは以下のように展開されます。
<%= text_field :person, :first_name %>
form_for
の一番右(ブロックを除く)の引数はオプションハッシュであり、以下のオプションを利用できます。
:url
- フォームの送信先URLです。ここには
url_for
やlink_to
に渡すのと同じフィールドを渡せます。名前付きルートを直接渡すこともできます。デフォルトは現在のアクションです。 :namespace
- フォーム要素のid属性を一意にするための名前空間を指定します。名前空間の属性の前には、生成されたHTML idの後ろにアンダースコア
_
を付けたものが追加されます。 :html
- フォームのタグにHTML属性を追加するのに使います。
form_for
は排他的なスコープを作成しないことにご注意ください。排他的なスコープの作成は、単独のFormHelperのメソッドとFormTagHelperのメソッドを両方使えば可能です。次の例をご覧ください。
<%= form_for @person do |f| %>
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
Biography : <%= text_area :person, :biography %>
Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
<%= f.submit %>
<% end %>
上の方法は、オブジェクトをベースとする設計になっているFormOptionHelperやDateHelperのメソッドでも使えます(FormOptionHelper#collection_selecやActionView::Helpers::DateHelper#datetime_select)。
リソース指向のスタイル
前述のとおり、#form_for
呼び出しは手動で設定できるほか、命名規則や名前付きルーティングに基いてリソースを自動識別することもできます。現在の#form_for
は、手動よりも自動化された方法で使うことが推奨されています。
たとえば、編集したい既存のレコード@post
があるとします。
<%= form_for @post do |f| %>
...
<% end %>
上のコード例は、以下ようなコードと同等です。
<%= form_for @post,
:as => :post,
:url => post_path(@post),
:method => :put,
:html => { :class => "edit_post", :id => "edit_post_45" } do |f| %>
...
<% end %>
新規レコードの場合は以下のように書けます。
<%= form_for(Post.new) do |f| %>
...
<% end %>
上のコード例は、以下ようなコードと同等です。
<%= form_for @post,
:as => :post,
:url => posts_path,
:html => { :class => "new_post", :id => "new_post" } do |f| %>
...
<% end %>
自動生成されるコードは、次のように上書きもできます。
<%= form_for(@post, :url => super_posts_path) do |f| %>
...
<% end %>
送信フォーマットも次のように指定できます。
<%= form_for(@post, :format => :json) do |f| %>
...
<% end %>
オブジェクトのパラメータを別の方法で表す必要がある場合は次のようにします。ここではPerson
をClient
として扱っています。
<%= form_for(@person, :as => :client) do |f| %>
...
<% end %>
admin_post_url:
のような名前空間化されたルーティングの場合は次のように書けます。
<%= form_for([:admin, @post]) do |f| %>
...
<% end %>
リソースに何らかの関連付けが定義されている場合は、ルーティングが正しく設定されているdocument
に次のようにcomment
を追加できます。
<%= form_for([@document, @comment]) do |f| %>
...
<% end %>
なお、上のコードでは@document = Document.find(params[:id])
および@comment = Comment.new
が設定されていることが前提です。
メソッドを設定する
オプションハッシュ内に次のように書くと、HTTP verbの完全な配列をフォームに渡して強制的に使うように設定できます。
:method => (:get|:post|:put|:delete)
こうすると、GET
やPOST
(これらはHTMLフォームでネイティブでサポートされます)でないverbが使われた場合に、フォームでPOST
が設定され、_method
と呼ばれる非表示のinputによって、サーバーが解釈できる期待どおりのverbが実行されます。
in the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the form will be set to POST and a hidden input called _method will carry the intended verb for the server to interpret.
「控えめなJavaScript」によるAjax
オプションハッシュで以下を指定すると、いわゆる「控えめな(unobtrusive)JavaScript」のドライバでフォームの挙動を変更できます。
:remote => true
このオプションを指定した場合のデフォルトの挙動では、通常のPOSTではなくXMLHttpRequestがバックグラウンドで動作することが期待されますが、最終的な動作はJavaScriptドライバの実装によって決定されます。
仮にフォームのさまざまな要素をJavaScriptによってシリアライズした場合でも、フォームを受信する側(つまりサーバー)から見ると通常の送信と同じ挙動になり、すべての要素をparamsで受け取れます。
次のコード例をご覧ください。
<%= form_for(@post, :remote => true) do |f| %>
...
<% end %>
上のERBによって次のHTMLが生成されます。
<form action='http://www.example.com' method='post' data-remote='true'>
<div style='margin:0;padding:0;display:inline'>
<input name='_method' type='hidden' value='put' />
</div>
...
</form>
非表示のモデルidを出力しないようにする
#form_for
メソッドを使うと、自動的にモデルidが隠しフィールドとしてフォームに含まれます。このモデルidは、フォームデータとそれに関連付けられているモデルとの関連を保つために使われます。
次の例では、NoSQLデータベースにPost
というモデルがひとつと、それに一対多で関連付けられるComment
というモデルが保存されています。:comments
には主キーはありません。
<%= form_for(@post) do |f| %>
<% f.fields_for(:comments, :include_id => false) do |cf| %>
...
<% end %>
<% end %>
フォームビルダをカスタマイズする
FormBuilderクラスをカスタマイズしてフォームをビルドすることもできます。カスタマイズするには、FormBuilderを継承してサブクラスを作り、必要なヘルパーメソッドを定義またはオーバーライドします。
<%= form_for @person, :url => { :action => "create" }, :builder => LabellingFormBuilder do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.text_area :biography %>
<%= f.check_box :admin %>
<%= f.submit %>
<% end %>
上のようにコードを書いてから、次のコードを書きます。
<%= render f %>
これにより、people/_labelling_form
というテンプレートを使ってレンダリング(=HTML生成)され、ローカル変数f
が参照するフォームビルダの名前はlabelling_form
となります。
特に指定しない限り、カスタムのFormBuilder
クラスは、ネストした#fields_for
呼び出しのオプションと自動的にマージされます。
上のようなコードを別のヘルパーにも含めておきたい場合は、以下のように書けます。
def labelled_form_for(record_or_name_or_array, *args, &block)
options = args.extract_options!
form_for(record_or_name_or_array, *(args << options.merge(:builder => LabellingFormBuilder)), &block)
end
モデルのインスタンスにフォームをアタッチする必要がない場合は、ActionView::Helpers::FormTagHelper#form_tagを参照してください。
外部リソースを使うフォーム
外部リソース(認証トークンの設定が必要な場合や、認証なしでフォームだけ表示したい場合などを含む)を扱うフォームをビルドする場合を考えてみましょう。何らかの支払い用ゲートウェイ番号にデータを送信しなければならず、フィールドの種類にも制限があるとします。
必要な認証トークンを渡すには、:authenticity_token
オプションを使います。
<%= form_for @invoice,
:url => external_url,
:authenticity_token => 'external_token' do |f| %>
...
<% end %>
認証トークンを一切出力したくない場合は、単にfalseを渡します
<%= form_for @invoice,
:url => external_url,
:authenticity_token => false do |f| %>
...
<% end %>