読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

Railsのビューヘルパー(View Helper)のまとめ

Rails初級 Rails View まとめ

Columbus Flickr Meet Group Photo
Photo by Columbus Flickr Meet Group Photo | Flickr - Photo Sharing!


Railsのよく忘れるプルダウン(select), チェックボックス(check_box), ラジオボタン(radio_button)などビューヘルパーをまとめました。

動作確認

  • Rails 4.2.0

目次

1. リンク - link_to
2. 画像 - image_tag
3. フォーム - form_for / form_tag
4. 関連モデルのフォームを作成 - fields_for
5. ラベル - label / label_tag
6. テキストフィールド - text_field / test_field_tag
7. 日付/時刻の入力フィールド - date_field / time_field / datetime_field
8. 日付/時刻の選択フィールド - date_select / time_select / datetime_select
9. ファイルアップロードフィールド - file_field / file_field_tag
10. テキストエリア - text_area / text_area_tag
11. プルダウン/セレクトボックス - select / select_tag / collection_select
12. チェックボックス - check_box / check_box_tag / collection_check_boxes
13. ラジオボタン - radio_button, radio_button_tag
14. hiddenフィールド - hidden_field / hidden_field_tag
15. サブミットボタン - submit / submit_tag



基本的な使い方

リンク(aタグ)を作成します。

link_to(name = nil, options = nil, html_options = nil, &block)

optionsに指定できるオプション

  • method ... :get, :post, :patch, :delete を指定することで、リンクのGET, POSTなどのHTTPメソッドを定義できる
  • remote: true ... Ajaxリクエストをサーバーに送る(デフォルト値:false)
  • data: { confirm: '削除しますか?' } ... "削除しますか?"という表示される確認ダイアログを表示する。
  • data: { disable_with: '更新中...' } ... ボタンを押した後に、ボタンを押せなくし、"更新中..."とボタンに表示する。

link_to の良くある使い方

# HTML属性を指定する
link_to "プロフィール", profile_path(@profile), class: "btn btn-large", id: "profile#{@profile.id}"
#=> <a class="btn btn-large" href="/profiles/1" id="profile1">プロフィール</a>


# クエリストリング(?=xxx)を追加する
link_to "プロフィール", profile_path(@profile, q: "list")
#=> <a href="/profiles/1?q=list">プロフィール</a>


# CSV, JSONなどリンクのフォーマットを指定する。
link_to "プロフィール", profile_path(@profile, format: 'csv')
#=> <a href="/profiles/1.csv">プロフィール</a>


# ブロックで特定要素を囲む
link_to "プロフィール", @profile do
  <strong><%= @profile.name %></strong>さんのプロフィール
end
#=> <a href="/profiles/1"><strong>鈴木</strong>さんのプロフィール</a>


# 条件によりリンクの表示有無を変える
# 管理者の場合、リンクを表示する。
link_to_if(current_user.admin?, "管理者用リンク", admin_path)


2. 画像 - image_tag

基本的な使い方

画像(imgタグ)を表示するために使います。

image_tag(source, options={})

オプション

  • source ... 絶対パスと相対パスのどちらでも指定可能。また、ファイルだけ指定した場合、assets/imagesフォルダからのパスとなる。
例: <%= image_tag 'picture.png' %>
#=> <img src="/images/picture.png" alt="Picture">
  • alt ... imgタグのalt属性(目の不自由な方のためなどの画像の代替文字列)を指定する。指定しない場合は、拡張子無しのファイル名が自動で設定される。
  • size ... "{幅}x{高さ}" か "{数}" のどちらかで指定する。"30x50"の場合、width="30" height="50"となる。"30"の場合、width="30" height="30"になる。
  • その他、HTMLのclassやid属性も追加することが可能
例: <%= image_tag "picture.png", class: "main_img" %>

iamge_tag のサンプル

image_tag("picture")
# => <img alt="Picture" src="/images/picture" />

image_tag("picture.png")
# => <img alt="Picture" src="/images/picture.png" />

image_tag("picture.png", size: "50x40", alt: "Home Image")
# => <img src="/images/picture.png" width="50" height="40" alt="Home Image" />

image_tag("/gallery/picture.png", size: "200")
# => <img src="/gallery/picture.png" width="200" height="200" alt="Picture" />

image_tag("picture.png", class: "menu_img")
# => <img alt="Picture" class="main_img" src="/images/picture.png" />


3. フォーム - form_for / form_tag

基本的な使い方(form_for と form_tag の使い分け方)

  • form_forは、モデルの作成や更新などモデルに紐付いたフォームを作成するために使います。モデルに紐付いているので、バリデーションエラー時にエラーメッセージとエラー箇所を表示することなどができます。
  • form_tagは、検索やレポート出力などモデルに紐付かないフォームを作成するために使います。モデルに紐付かないので、基本的にはバリデーションはできません。メソッドはlabel_tagなどxxx_tagメソッドを使います。
form_for(record, options = {} &block)
form_tag(url_for_options = {}< options = {}, &block)

オプション

  • url ... submitするURL。form_forの場合、モデルから自動的にURLが生成されるため必ずしも必要ではない。form_tagの場合、必ず必要。
  • method ... :get, :post, :patch, :delete を指定することで、フォームのGET, POSTなどのHTTPメソッドを定義できる
  • remote ... trueを設定するとAjaxのsubmitになる。(デフォルト: false)
  • html ... formタグのHTML属性を指定する
<%= form_for @user, remote: true, :html => { :class => "form-horizontal", :role => "form" } do |f| %>
  # userの属性を指定
  <%= f.text_field :name %>
  <%= f.number_field :age %>
  ...
  <%= f.submit %>
<% end %>


# config/routes.rb の resources が次のように入れ子の場合、
#  resources :users do
#    resources :comments
#  end
# form_forにモデルを配列で指定する
<%= form_for [@usre, @comments] do |f| %>
  <!-- commentの属性を指定 -->
  <%= f.text_field :content %>
  ...
<% end %>


4. 関連モデルのフォームを作成 - fields_for

has_onehas_manyで関連づいたモデルも同時に作成/更新できるフォームを作成します。
次のようにモデルごとにフォームを入れ子にします。

<%= form_for @user do |f| %>
  ...
  <%= f.fields_for :address do |address_fields| %>
    Street  : <%= address_fields.text_field :street %>
    Zip code: <%= address_fields.text_field :zip_code %>
  <% end %>
  ...
<% end %>


関連モデルの作成/更新をするには、ビューだけでなくモデルやコントローラーにも実装が必要です。一般的にfields_forと一緒にaccepts_nested_attributes_forを使います。
関連モデルも一度に作成/更新するフォームを作りたい場合は、「Railsでaccepts_nested_attributes_forとfields_forを使ってhas_many関連の子レコードを作成/更新するフォームを作成 - Rails Webook」を参照してください。




5. ラベル - label / label_tag

ラベル(label要素)を作成します。

<%= f.label(:name, "名前") %>
#=> <label for="user_name">名前</label>


<%= label_tag(:user, "名前") %>
#=> <label for="user">名前</label>


6. テキストフィールド - text_field / test_field_tag

テキストフィールド(<input type="text">要素)を作成します。

# 編集時にはvalueにはモデルのname属性の値が入る
<%= f.text_field :name %>
#=> <input type="text" name="user[name]" id="user_name">


<%= text_field_tag "user[name]", "" %>
#=> <input type="text" name="user[name]" id="user_name" value="値">
<%= f.text_field(:name, "名前") %>

text_fieldのオプション

  • :disabled ... trueを設定すると入力不可にできる。
  • :size ... 指定した数の文字数分だけ表示できる幅に広がる。
  • :maxlength ... ユーザが入力可能な最大文字数
  • :placeholder ... プレイスホルダーを設定する。
  • その他、どんなHTML属性をも設定できる。

その他のテキストフィールド

テキストフィールドと同じように、次のようなフィールドも作成できます。

  • メールアドレスフィールド(type="email") email_field / email_field_tag
  • パスワードフィールド(type="password) password_field / password_field_tag
  • 検索フィールド(type="search") search_field / search_field_tag
  • 数値フィールド(type="number") number_field / number_field_tag

7. 日付/時刻の入力フィールド - date_field / time_field / datetime_field

日付フィールド(type="date)

date_field / date_field_tagで作成できます。
f:id:nipe880324:20150110140026j:plain:w180

時刻フィールド(type="time)

time_field / time_field で作成できます。
f:id:nipe880324:20150110140044j:plain:w180

日付時刻フィールド(input type="datetime")

datetime_field / datetime_field_tagで作成できます。
f:id:nipe880324:20150110140057j:plain:w180



日付/時刻の選択フィールド - date_select / time_select / datetime_select

日付選択フィールド - time_select

日付のセレクトフィールドが作成します。
f:id:nipe880324:20150110140321j:plain:w180

<%= f.time_select :activated_at %>

# =>
# <select id="user_activated_at_1i" name="user[activated_at(1i)]">
#   <option value="2010">2010</option>
#   <option value="2011">2011</option>
#   ... 年
#   <option value="2020">2020</option>
# </select>
# <select id="user_activated_at_2i" name="user[activated_at(2i)]">
#   <option value="1" selected="selected">January</option>
#   <option value="2">Feburary</option>
#   ... 月
#   <option value="12">December</option>
# </select>
# <select id="user_activated_at_3i" name="user[activated_at(3i)]">
#   <option value="1">1</option>
#   <option value="2">2</option>
#   ... 日
#   <option value="31">31</option>
# </select>

# paramsの値
{
  "user" => {
    "name" => "ユーザー名",
    "activated_at(1i)"=>"2015",
    "activated_at(2i)"=>"1",
    "activated_at(3i)"=>"8"
    },
  "commit"=>"Create User"
}

様々なオプションがあるのでRails APIを参照してください。


時刻選択フィールド - time_select

時刻のセレクトフィールドが作成されます。
f:id:nipe880324:20150110140357j:plain:w180

<%= f.time_select :activated_at %>

# =>
# <input type="hidden" id="user_activated_at_1i" name="user[activated_at(1i)]" value="2015">
# <input type="hidden" id="user_activated_at_2i" name="user[activated_at(2i)]" value="1">
# <input type="hidden" id="user_activated_at_3i" name="user[activated_at(3i)]" value="8">
# <select id="user_activated_at_4i" name="user[activated_at(4i)]">
#   <option value="00">00</option>
#   <option value="01">01</option>
#   ... 時
#   <option value="24">24</option>
# </select>
#  : 
# <select id="user_activated_at_5i" name="user[activated_at(5i)]">
#   <option value="00">00</option>
#   <option value="01">01</option>
#   ... 分
#   <option value="59">59</option>
# </select>


# デフォルトだとparamsに年月日も送られます。
# 未入力でも、勝手にデータが作成される可能性があります。
{
  "user"=>{
    "name" => "ユーザー名",
    "activated_at(1i)" => "2015",
    "activated_at(2i)" => "1",
    "activated_at(3i)" => "8",
    "activated_at(4i)" => "14",
    "activated_at(5i)" => "59"
  },
  "commit"=>"Create User"
}


上記で記載しましたが、場合によって、include_blank: trueignore_date: trueを指定することで、未入力の場合に年月日が送られないようにできます。
そうすることで、モデル側のpresenceなどのバリデーションを上手く機能させることができるようになります。

<%= f.time_select :activated_at, include_blank: true, ignore_date: true %>

# =>
# 年月日のhiddenフィールドが作成されない
# <select id="user_activated_at_4i" name="user[activated_at(4i)]">
#   <option value="00">00</option>
#   <option value="01">01</option>
#   ... 時
#   <option value="24">24</option>
# </select>
#  : 
# <select id="user_activated_at_5i" name="user[activated_at(5i)]">
#   <option value="00">00</option>
#   <option value="01">01</option>
#   ... 分
#   <option value="59">59</option>
# </select>

# 年月日がparamsになくなる
{
  "user" => {
    "name" => "",
    "activated_at(4i)" => "15",
    "activated_at(5i)" => "03"
  },
  "commit"=>"Create User"
}

他にも秒数を表示など様々なオプションがあるのでRails APIを参照してください。


日付時刻選択フィールド - datetime_select

日付と時刻のセレクトフィールドが作成されます。
f:id:nipe880324:20150110141729j:plain:w180

<%= f.datetime_select :activated_at %>

# =>
# <div class="field">
# <select id="user_activated_at_1i" name="user[activated_at(1i)]">
#   <option value="2015" selected="selected">2015</option>
#   <option value="2016">2016</option>
#     ... 年
# </select>
# <select id="user_activated_at_2i" name="user[activated_at(2i)]">
#   <option value="1" selected="selected">January</option>
#   <option value="2">February</option>
#     ... 月
#   <option value="12">December</option>
# </select>
# <select id="user_activated_at_3i" name="user[activated_at(3i)]">
#   <option value="1">1</option>
#   <option value="2">2</option>
#     ... 日
#   <option value="31">31</option>
# </select>
#  —
# <select id="user_activated_at_4i" name="user[activated_at(4i)]">
#   <option value="00">00</option>
#   <option value="01">01</option>
#     ... 時
#   <option value="23">23</option>
# </select>
#  :
#  <select id="user_activated_at_5i" name="user[activated_at(5i)]">
#   <option value="00">00</option>
#   <option value="01">01</option>
#     ... 分
#   <option value="59">59</option>
# </select>


# paramsは年月日と時刻が送られれます。
{
  "user" => {
    "name" => "ユーザー名",
    "activated_at(1i)" => "2015",
    "activated_at(2i)" => "1",
    "activated_at(3i)" => "8",
    "activated_at(4i)" => "15",
    "activated_at(5i)" => "09"
  },
  "commit"=>"Create User"
}


9. ファイルアップロードフィールド - file_field / file_field_tag

ファイルをアップロードするための<input type="file">要素を作成します。
f:id:nipe880324:20150110140555j:plain:w180

<%= f.file_field(:iamge) %>
#=> <input type="file" name="user[image]" id="user_image">


<%= file_field_tag "user[image]" %>
#=> <input type="file" name="user[image]" id="user_image">


# form_for の場合は必要ないが、form_tagの場合、form_tag に multipart: true オプションが必要。
<%= form_tag url: upload_users_path, multipart: true do |f| %>
  <%= f.file_field(:iamge) %>
<% end %>


10. テキストエリア - text_area / text_area_tag

テキストエリアを作成します。
f:id:nipe880324:20150110141743j:plain:w180

<%= f.text_area :name %>
#=> <input type="file" name="user[image]" id="user_image">


<%= text_area_tag "user[name]", "" %>
#=> <textarea name="user[name]" id="user_name">値</textarea>

オプション

  • :size - A string specifying the dimensions (columns by rows) of the textarea (e.g., “25x10”).
  • :rows - Specify the number of rows in the textarea
  • :cols - Specify the number of columns in the textarea
  • :disabled - If set to true, the user will not be able to use this input.
  • :escape - By default, the contents of the text input are HTML escaped. If you need unescaped contents, set this to false.
  • Any other key creates standard HTML attributes for the tag.



11. プルダウン/セレクトボックス - select / select_tag / collection_select

プルダウンであるselect要素が作成されます。
f:id:nipe880324:20150110141809j:plain:w180

# どのメソッド結果は同じです
# 「属性名」、「配列データ」,「Option要素のvalueに設定するカラム名」, 「Option要素に表示するカラム名」の順で指定します。
<%= f.select :prefecture_id, Prefecture.all.map { |p| [p.name, p.id] } %>
<%= select_tag "address[prefeture_id]", options_from_collection_for_select(Prefecture.all, :id, :name) %>
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name %>
# =>
# <select name="address[prefecture_id]" id="address_prefecture_id">
#   <option value="1">東京都</option>
#   <option value="2">神奈川県</option>
#   <option value="3">埼玉県</option>
# </select>

オプション

  • :multiple - If set to true the selection will allow multiple choices.
  • :disabled - If set to true, the user will not be able to use this input.
  • :include_blank - If set to true, an empty option will be created. If set to a string, the string will be used as the option's content and the value will be empty.
  • :prompt - Create a prompt option with blank value and the text asking user to select something.
  • :selected - Provide a default selected value. It should be of the exact type as the provided options.
  • Any other key creates standard HTML attributes for the tag.


また、select2という検索可能なプルダウンを作成するjQueryプラグインもあります。
f:id:nipe880324:20150110141855j:plain:w220

Railsへの導入方法は、「Railsで検索可能なセレクトボックスのselect2を使う方法]」を参照してください。




12. チェックボックス - check_box / check_box_tag / collection_check_boxes

チェックボックスが作成されます。

単一のチェックボックスの作成

f:id:nipe880324:20150110140828j:plain:w180

# チェックボックスを1つ作成する
<%= f.check_box :discontinued %> <%= f.label :discontinued, "販売停止" %>
# =>
# <input name="product[discontinued]" type="hidden" value="0">
# <input type="checkbox" value="1" name="product[discontinued]" id="product_discontinued"> <label for="user_discontinued">販売停止</label>


# チェックボックスを1つ作成する
<%= check_box_tag "product[discontinued]" %> <%= label_tag "product[discontinued]", "販売停止" %>
# =>
# <input type="checkbox" name="product[discontinued]" id="product_discontinued" value="1"> <label for="product_discontinued">販売停止</label>

複数のチェックボックスの作成

f:id:nipe880324:20150110140843j:plain:w180

ProductとCategoryが「N対N関係」である前提でビューを記載しています。

<% Category.all.each do |category| %>
  <%= check_box_tag "product[category_ids][]", category.id, @product.categories.include?(category), id: "product_category_ids_#{category.id}" %>
  <%= label_tag "product[category_ids][#{category.id}]", category.name %>
<% end %>

# =>
# <input type="checkbox" name="product[category_ids][]" id="product_category_ids_1" value="1">
# <label for="product_category_ids_1">カテゴリ1</label>
# <input type="checkbox" name="product[category_ids][]" id="product_category_ids_2" value="2">
# <label for="product_category_ids_2">カテゴリ2</label>
# <input type="checkbox" name="product[category_ids][]" id="product_category_ids_3" value="3">
# <label for="product_category_ids_3">カテゴリ3</label>

# paramsは次のようになります。
# チェック0個の場合
"product"=>{"name"=>""}
# チェック1個以上
"product"=>{"name"=>"", category_ids"=>["1", "2"]}


# コントローラーのStrongParameters部分では、category_ids => [] と記載し配列を許可するようにします。
def product_params
  params.require(:product).permit(:name, :category_ids => [])
end


# 「多対多関係」をモデルで定義しておくとProductのcateogyr_ids属性に配列でカテゴリIDを設定することでhas_manyメソッドのおかげで複数のINERT文が走ります。
Parameters: {product"=>{"name"=>"Aaa", "price"=>"100", "category_ids"=>["1", "2"]}, "commit"=>"Create Product"}
Category Load (0.3ms)  SELECT "categories".* FROM "categories" WHERE "categories"."id" IN (1, 2)
begin transaction
  # Prodctに1レコード追加される
  SQL (0.4ms)  INSERT INTO "products" ("name", "price", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Aaa"], ["price", 100], ["created_at", "2015-01-10 03:51:29.408266"], ["updated_at", "2015-01-10 03:51:29.408266"]]
  # ProductとCategoryの中間テーブルが2列追加されている
  SQL (0.2ms)  INSERT INTO "product_categories" ("category_id", "product_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["category_id", 1], ["product_id", 3], ["created_at", "2015-01-10 03:51:29.410606"], ["updated_at", "2015-01-10 03:51:29.410606"]]
  SQL (0.1ms)  INSERT INTO "product_categories" ("category_id", "product_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["category_id", 2], ["product_id", 3], ["created_at", "2015-01-10 03:51:29.414744"], ["updated_at", "2015-01-10 03:51:29.414744"]]
commit transaction


同じく「多対多関連」が前提で、次のような記載方法もあります。

<%= f.collection_check_boxes :category_ids, Category.all, :id, :name %>


13. ラジオボタン - radio_button, radio_button_tag

ラジオボタンを作成します。
f:id:nipe880324:20150110140911j:plain:w180

<%= f.label :rate %><br>
<%= f.radio_button :rate, 1 %> <%= f.label :rate_1, 1 %>
<%= f.radio_button :rate, 2 %> <%= f.label :rate_2, 2 %>
<%= f.radio_button :rate, 3 %> <%= f.label :rate_3, 3 %>
<%= f.radio_button :rate, 4 %> <%= f.label :rate_4, 4 %>
<%= f.radio_button :rate, 5 %> <%= f.label :rate_5, 5 %>
# =>
<label for="product_rate">Rate</label><br>
<input type="radio" value="1" name="product[rate]" id="product_rate_1"> <label for="product_rate_1">1</label>
<input type="radio" value="2" name="product[rate]" id="product_rate_2"> <label for="product_rate_2">2</label>
<input type="radio" value="3" name="product[rate]" id="product_rate_3"> <label for="product_rate_3">3</label>
<input type="radio" value="4" name="product[rate]" id="product_rate_4"> <label for="product_rate_4">4</label>
<input type="radio" value="5" name="product[rate]" id="product_rate_5"> <label for="product_rate_5">5</label>


セレクトボックスのように一度にモデルの配列を返すことで、ラジオボックスを作成することも可能です。

<%= f.collection_radio_buttons :maker_id, Maker.all, :id, :name %>
# =>
# <input type="radio" value="1" name="product[maker_id]" id="product_maker_id_1"><label for="product_maker_id_1">カテゴリ1# </label>
# <input type="radio" value="2" name="product[maker_id]" id="product_maker_id_2"><label for="product_maker_id_2">カテゴリ2# </label>
# <input type="radio" value="3" name="product[maker_id]" id="product_maker_id_3"><label for="product_maker_id_3">カテゴリ3# </label>


14. hiddenフィールド - hidden_field / hidden_field_tag

隠し入力フィールド(画面に表示されない)を作成できます。
ユーザーからhiddenフィールドの値を見ることができるので、ユーザーに見られて困る秘密情報は載せないようにする必要があります。

<%= f.hidden_field :lock_version %>
#=> <input type="hidden" name="product[lock_version]" id="product_lock_version" value="1">


<%= hidden_field_tag "product[lock_version]", @product.lock_version %>
#=> <input type="hidden" name="product[lock_version]" id="product_lock_version" value="1">

15. サブミットボタン - submit / submit_tag

サブミットボタンを作成します。
f:id:nipe880324:20150110141646j:plain:w180

<%= f.submit "登録" %>
#=> <input type="submit" name="commit" value="登録">

<%= submit_tag "検索" %>
 #=> <input type="submit" name="commit" value="検索">


1つのフォームに複数のサブミットボタンを追加して処理を分けたい場合は、「Railsで1フォームに複数のサブミット(Submit)ボタンを配置するTips」を参照してください。


以上です。