フォーム関連の記述に役立つビューヘルパーの使い方 (Rails4)
[履歴] [最終更新] (2014/10/08 10:01:31)
最近の投稿
注目の記事

概要

他のMVCフレームワークと同様に、Rails4にも様々なビューヘルパーが用意されています。そのうち、ここでは特にフォーム関連のタグを生成するためのヘルパーの使用方法についてまとめてみます。

事前準備

ビューヘルパーのサンプルを実行するために、

$ rails generate scaffold myModel field1:string field2:integer field3:date field4:boolean
$ rake db:migrate

を実行しておきましょう。それらの意味についてはこちらを参照してください。また、サンプル実行時のエラー回避のために、ルーティングを一つ追記しておきましょう。

config/routes.rb

MyApp::Application.routes.draw do
  resources :my_models

  match ':controller(/:action(/:id))', via: [ :get, :post, :patch ] # ←追記
...

簡単なサンプルコード

1. モデルに依存しないデータのみをPOSTするフォーム

form_tagヘルパーを使用します。フォーム内部では xxx_tagヘルパーを使用します。

app/views/my_models/new.html.erb

<%= form_tag({ controller: :main, action: :search }, id: :css_id, class: :css_class) do %>
<%= text_field_tag :search_box, '', size: 50 %>
<%= submit_tag '検索実行' %>
<% end %>

生成結果例

<form accept-charset="UTF-8" action="/main/search" class="css_class" id="css_id" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="tjI9oVd9hfvuNsX7IaVIf0Hu4rjf3nr9/sbda6II3GQ=" />
  </div>
  <input id="search_box" name="search_box" size="50" type="text" value="" />
  <input name="commit" type="submit" value="検索実行" />
</form>

2. モデルに依存したデータを含んでPOSTするフォーム (依存しないデータもPOST可能)

form_forヘルパーを使用します。フォーム内部では

  • モデルに依存するデータは、f.xxxヘルパー (valueには適宜自動で値が設定されます)
  • モデルに依存しないデータは、xxx_tagヘルパー

を使用します。

app/controllers/my_models_controller.rb

# GET /my_models/new
def new
  @my_model = MyModel.new
end

app/views/my_models/new.html.erb

<%= form_for(@my_model) do |f| %>
  <%= f.label :field1 %>
  <%= f.text_field :field1, size: 30 %>
  備考:
  <%= text_field_tag :additional_info, '', size: 30 %>
  <%= f.submit %>
<% end %>

出力結果例

<form accept-charset="UTF-8" action="/my_models" class="new_my_model" id="new_my_model" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="tjI9oVd9hfvuNsX7IaVIf0Hu4rjf3nr9/sbda6II3GQ=" />
  </div>
  <label for="my_model_field1">Field1</label>
  <input id="my_model_field1" name="my_model[field1]" size="30" type="text" />
  備考:
  <input id="additional_info" name="additional_info" size="30" type="text" value="" />
  <input name="commit" type="submit" value="Create My model" />
</form>

その他のフォームヘルパー

app/controllers/my_models_controller.rb

# GET /my_models/new
def new
  @my_model = MyModel.new(field1: '次郎') # セレクタ等で既定値を与える方法の一つ
  @my_models = MyModel.select(:field1).distinct # SELECT DISTINCT field1 FROM my_models
end

app/views/my_models/new.html.erb

<%= form_for(@my_model) do |f| %>

  <!-- テキストエリア -->
  <%= f.text_area :field1, cols: 20, rows: 2 %>

  <!-- パスワード -->
  <%= f.password_field :field1, size: 20, maxlength: 20 %>

  <!-- チェックボックス -->
  <%= f.check_box :field2, {class: 'html-class', checked: true}, 'yes', 'no' %>
  <!-- ← チェックされなかったらinput-hidden(自動生成)で'no'を返す -->
  <%= f.label :field2, '許可' %>

  <!-- ラジオボタン -->
  <label><%= f.radio_button :field3, '白', {checked: true} %>白</label>
  <label><%= f.radio_button :field3, '黒' %>黒</label>

  <!-- DBから自動生成するチェックボックス -->
  <%= f.collection_check_boxes(:field1, @my_models, :field1, :field1) %>
  <!-- @my_modelsはコントローラでSELECTしておいた変数 -->
  <!-- 最後二つの ":field1" はそれぞれ、valueおよびラベルテキストに表示する列を指定 -->

  <!-- DBから自動生成するラジオボタン -->
  <%= f.collection_radio_buttons(:field1, @my_models, :field1, :field1) %>

  <!-- Hidden -->
  <%= f.hidden_field :field1 %>

  <!-- ローカルファイル選択 -->
  <%= f.file_field :field1 %>

  <!-- HTML5 -->
  <%= f.range_field :field1, min: 0, max: 50 %>
  <%= f.number_field :field1, min: 1, max: 25, step: 1 %>
  <%= f.color_field :field1 %>
  <%= f.date_field :field1 %>
  <%= f.time_field :field1 %>

  <!-- 基本的なセレクト -->
  <%= f.select :field1, ['紅組', '白組'],
      { include_blank: '選択してください'}, class: 'html-class' %>

  <%= f.select :field1, {'紅組' => 1, '白組' => 2},
      { include_blank: '選択してください'}, class: 'html-class' %><!-- テキストとvalueを違えたい場合 -->

  <%= select_tag 'selector-id', options_for_select(
      {'小学校' => 1, '中学校' => 2, '高等学校' => 3}, 2) %><!-- モデルに依存しないセレクト -->

  <!-- リストボックス -->
  <%= f.select :field1, ['一郎', '次郎', '三郎', '四郎'], {}, multiple: true, size: 3 %>
  <%= select_tag 'selector-id', options_for_select(
      ['小学校', '中学校', '高等学校', '大学']), multiple: true, size: 3 %><!-- モデルに依存しないリストボックス -->

  <!-- DBから自動生成するセレクト -->
  <%= f.collection_select :field1, @my_models, :field1, :field1 %>
  <!-- @my_modelsはコントローラでSELECTしておいた変数 -->
  <!-- 最後二つの ":field1" はそれぞれ、valueおよびテキストに表示する列を指定 -->
  <%= select_tag 'selector-id', options_from_collection_for_select(
      @my_models, :field1, :field1, 'ここにdefaultを指定可能') %><!-- モデルに依存しないセレクト -->

  <!-- DBから自動生成するグループセレクト -->
  <%# f.grouped_collection_select :field1, @listA, :listB, :f1, :f2, :f3 %>
  <!-- 前提: -->
  <!-- "my_models":"listB" = N:1 -->
  <!-- listBのフィールドの一部: ":f1",":f2",":f3" -->
  <!-- ":f1": optgroupのlabelに指定される -->
  <!-- ":f2": optionのvalueに指定される -->
  <!-- ":f3": optionのテキストに指定される -->
  <!-- "listA"は複数の"listB"を持つ -->
  <!-- コントローラにて: @listA=ListA.all -->
  <%# select_tag 'selector-id',
      option_groups_from_collection_for_select(@listA, :listB, :f1, :f2, :f3) %>
      <!-- モデルに依存しないセレクト -->

  <!-- 日付および時刻セレクト -->
  <%= f.date_select :field3, use_month_numbers: true %>
  <%= f.time_select :field3  %>

  <!-- アソシエートされた別のモデルを更新するサブフォーム -->
  <%# field_set_tag 'サブフォーム' do %>
    <%# fields_for @my_model.modelC do |cf| %>
      <%# cf.label :f1 %>
      <%# cf.text_field :f1 %>
    <%# end %>
  <%# end %>
  <!-- 前提: -->
  <!-- "my_models":"modelC" = 1:1 -->
  <!-- 1:N の場合は「@my_model.modelCList.each do |modelC|」としてから "fields_for @modelC" とする -->
  <!-- modelCのフィールドの一部: ":f1" -->
  <!-- 結果: -->
  <!-- "name=modelC[f1]"のようなHTMLが生成される -->
  <!-- "name=my_model[field1]"と別のハッシュとしてコントローラで取得 -->
  <!-- → params.require(:modelC).permit(:f1) -->

  <!-- サブミット -->
  <%= f.submit '実行', data: {
      confirm: '実行してもよいですか?',
      disable_with: '処理中です...'} %>
<% end %>
関連ページ
    概要 Spring Boot のテンプレートエンジンとしては、こちらで使用方法を把握した Thymeleaf が有名です。本ページでは、フォーム関連の処理について、基本的なサンプルコードをまとめます。Rails におけるビューヘルパーや、フォーム入力値のバリデーションに相当する機能です。 公式ドキュメント Handling Form Submission