他の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 ] # ←追記
...
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="✓" />
<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>
form_forヘルパーを使用します。フォーム内部では
を使用します。
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="✓" />
<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 %>