2011年6月20日月曜日

[Rails3] form_for と form_tag、text_field と text_field_tag の違い

実行環境:
Rails 3.0.7

ftext_field と text_field_tag の使い分けについて


Scaffold を作った時に自動的にできてくる View(_form.html.erb)を見ると

<%= form_for(@hoge) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
ってな感じで f.text_field を使っています。

特定のモデルに結びついたフォームならこれでいいんですが、そうでない場合は form_for ではなく form_tag を使う、ってとこまでは理解していたんですが、form_tag の中の部品については text_field_tag を使う?でも text_field タグも使えちゃうみたいよ、どうすんだ??と漠然と疑問だったので調べてみました。

その結果は

まぁ、その通りでございますね (^^;;; やっぱり form_for の時は text_field グループを使う、form_tag の時は text_field_tag グループを使うってことで基本的にはいいようです。

しか〜し、これでは再確認しただけで当初の疑問は解決してまへん。もうちょっとつっこんで調べてみると、どうやら params への値の渡り方にポイントがあるようです。

結論としては

  • text_field グループ
    考え方:モデルを対象として、モデルの値を受け渡すためのフォーム部品
    振舞い:params 変数に二次元のハッシュとして値を渡す(一次元目のキーがモデル名)
  • text_field_tag グループ
    考え方:モデルには関連づけず、値のみを単純に渡すフォーム部品
    振舞い:params 変数に一次元のハッシュとして値を渡す
ということになります。

 

まとめるとそういうことなんですが、一応それぞれの場合を整理してみます。

form_forの中でform_tagの中で
text_fieldグループを①(標準的)②(特殊?)
text_field_tagグループを④(特殊?)③(標準的)

① text_field グループを form_for 内で使う(標準的)
Scaffold として作られる以下のようなフォームの場合、
<%= form_for(@hoge) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
受け側で受け取るフォームの値は params[:hoge][:name] となります。 通常、モデルの作成や更新に使う場合
create アクション
@hoge = Hoge.new(params[:hoge])
update アクション
@hoge = Hoge.find(params[:id]) @hoge.update_attributes(params[:hoge])
といった具合で便利にできるので params の中身をことさらに気にする必要はないんですね。

② text_field グループを form_tag 内で使う場合(特殊ケース)
form_tag の中で text_field を使うときは少しパラメータの与え方が違って
form_tag の中で text_field
<%= form_tag url, options do %> <%= text_field :hoge, :name, :value => 'default_name' %> <%= submit_tag %> <% end %>
という感じになります。form_tag の中で text_field という形で使うと1番目と2番目のパラメータが名前として使われ、params[:hoge][:name] に値が渡されます。 HTML としてはこんな感じで展開されます。
展開された HTML
<input type="text" id="hoge_name" name="hoge[name]" value="default_name" />
params にハッシュで構造化した値を渡したいときは便利かもしれません。どんな用途があるかパッと思いつきませんが。 ハッシュにしたくないよってときは強引ですが
form_tag の中で text_field
<%= form_tag url, options do %> <%= text_field nil, nil, :id => name, :name => name, :value => 'default_name' %> <% end %>
とすれば
展開された HTML
<input type="text" id="name" name="name" value="default_name" />
と展開されますが、それならおとなしく text_field_tag 使えばって話です (^^;

③ text_field_tag グループを form_tag 内で使う(標準的)
form_tag の中で text_field_tag
<%= form_tag url, options do %> <%= text_field_tag :name, :value => 'default_name' %> <% end %>
とすると params[:name] に値が渡ります。

④ text_field グループを form_for 内で使う(特殊だけど使い道ありそう)
まず、以下のような書き方はできません。
form_for の中で text_field_tag
<%= form_for(@hoge) do |f| %> <%= f.text_field_tag :extra_text %> <% end %>
form_for の中でも form_tag の中でも使い方や挙動は同じです。
form_for の中で text_field_tag
<%= form_for(@hoge) do |f| %> <%= text_field_tag :name, :value => 'default_name' %> <% end %>
とするとやはり params[:name] に値が渡ります。注意すべきは params[:hoge][:name] のように params[:hoge] 配下に入らないということです。
form_for の中で text_field_tag
<%= form_for(@hoge) do |f| %> <%= text_field_tag :extra_text %> <%= f.text_field :name %> <%= f.submit %> <% end %>
という書いてやると、Hoge モデルに対応したパラメータ params[:hoge][:name] と、モデルとは関係ない params[:extra_text] を同時に渡せることになります。 場合によっては便利に使える気がします!(たぶん)

0 件のコメント:

コメントを投稿