form関連のビューヘルパー

form

  • formの生成は、大きく2つ
  • form_tagは、汎用フォーム用
    • textl_tag,text等のヘルパーが使用可能
    • 無理にbook[isbn]へのアクセスするなら、text_fieldを使ってこんな感じ?
      <%= form_tag({ :action => 'create' }) do %>
        <%= text_field :book, :isbn, { :size => 25 } %>
      <% end %>
      
  • form_forは、モデル用
    • text_tag,f.text等のヘルパーが使用可能
    • こっちならbook[isbn]へのアクセスも見やすい
      <%= form_for(@book) do |f| %>
        <%= f.text_field :isbn, { :size => 25 } %>
      <% end %>
      
  • あ、form_forだとactionを指定してないけど、これは自動で処理されるんだ!すげー
    • 要するに、@bookが空ならid="new_book"に、findの結果が入ってればid="edit_book"になる。
    • この辺は、例のresourcesで定義されたアクセスルートが影響してくるんだね。
  • これらで生成されるform中のinputタグには、自動でIDが付与されるんだ。
    • 例えば、name="book[isbn]"の場合、id="book_isbn"みたいに。

input/textarea

  • こんな感じで書くと
    <%= form_for(@book) do |f| %>
     <div class="field">
       テキスト:<%= f.text_field :isbn, :read_only => true %><br/>
       パスワード:<%= f.password_field :isbn, :disabled => true %><br/>
       テキストエリア:<%= f.text_area :isbn, :cols => 40 %><br/>
       ラジオ:
       <label><%= f.radio_button :publish, '出版社A', {:class => 'rd'} %></label>
       <label><%= f.radio_button :publish, '出版社B', {:class => 'rd'} %></label>
       <br/>
       チェックボックス:<label><%= f.check_box :cd, {:class => 'chk'}, 'yes', 'no'  %>CD付属?</label><br/>
       ファイル:<%= f.file_field :isbn %><br/>
       Hidden:<%= f.hidden_field :isbn %>ここは、当然見えないはずw<br/>
     </div>
    <% end %>
    
  • HTMLはこんな感じ
    <form accept-charset="UTF-8" action="/books" class="new_book" enctype="multipart/form-data" id="new_book" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="***********************************************" /></div>
     <div class="field">
       テキスト:<input id="book_isbn" name="book[isbn]" read_only="true" size="30" type="text" /><br/>
       パスワード:<input disabled="disabled" id="book_isbn" name="book[isbn]" size="30" type="password" /><br/>
       テキストエリア:<textarea cols="40" id="book_isbn" name="book[isbn]" rows="20"></textarea><br/>
       ラジオ:
       <label><input class="rd" id="book_publish_a" name="book[publish]" type="radio" value="出版社A" /></label>
       <label><input class="rd" id="book_publish_b" name="book[publish]" type="radio" value="出版社B" /></label>
       <br/>
       チェックボックス:<label><input name="book[cd]" type="hidden" value="no" /><input class="chk" id="book_cd" name="book[cd]" type="checkbox" value="yes" />CD付属?</label><br/>
       ファイル:<input id="book_isbn" name="book[isbn]" type="file" /><br/>
       Hidden:<input id="book_isbn" name="book[isbn]" type="hidden" />ここは、当然見えないはずw<br/>
     </div>
    </form>
    
    • 存在しないプロパティを指定すると、エラーになるらしい
    • check_boxは、2つのinput(hiddenとcheckbox)を出力するんだ!これは 「チェックされなかった」 ことを判定するためみたい。すげー
  • HTML5も対応してる
    • こう書けば、
       <div class="field">
         メール:<%= f.email_field :isbn %><br/>
         数値:<%= f.number_field :isbn, {:step => 10} %><br/>
         範囲:<%= f.range_field :isbn, {:max => 100, :min => 10} %><br/>
         検索:<%= f.search_field :isbn %><br/>
         電話:<%= f.telephone_field :isbn %><br/>
         URL:<%= f.url_field :isbn %><br/>
       </div>
      
    • こう出る
       <div class="field">
         メール:<input id="book_isbn" name="book[isbn]" size="30" type="email" /><br/>
         数値:<input id="book_isbn" name="book[isbn]" size="30" step="10" type="number" /><br/>
         範囲:<input id="book_isbn" max="100" min="10" name="book[isbn]" size="30" type="range" /><br/>
         検索:<input id="book_isbn" name="book[isbn]" size="30" type="search" /><br/>
         電話:<input id="book_isbn" name="book[isbn]" size="30" type="tel" /><br/>
         URL:<input id="book_isbn" name="book[isbn]" size="30" type="url" /><br/>
       </div>
      

リストボックス系

  • シンプルに書くのは、select
    • こんな感じで書くと
         リストボックス(最低限):<%= f.select(:publish, ['出版社A','出版社B'])  %><br/>
         リストボックス(空指定):<%= f.select(:publish, ['出版社A','出版社B'], { :include_blank => '選択して下さい'} )%><br/>
         リストボックス(ハッシュ):<%= f.select(:publish, { '出版社A' => 1,'出版社B' => 2 })%><br/>
         リストボックス(配列):<%= f.select(:publish, [['出版社A',1],['出版社B',2]] )%><br/>
         リストボックス(複数指定):<%= f.select(:publish, ['出版社A','出版社B'], {}, { :multiple => true })  %><br/>
      
    • こう出る
      • リストボックス(最低限):
        <select id="book_publish" name="book[publish]">
        <option value="出版社A">出版社A</option>
        <option value="出版社B">出版社B</option></select><br/>
        
      • リストボックス(空指定):
        <select id="book_publish" name="book[publish]">
        <option value="">選択して下さい</option>
        <option value="出版社A">出版社A</option>
        <option value="出版社B">出版社B</option></select><br/>
        
      • リストボックス(ハッシュ):
        <select id="book_publish" name="book[publish]">
        <option value="1">出版社A</option>
        <option value="2">出版社B</option></select><br/>
        
      • リストボックス(配列):
        <select id="book_publish" name="book[publish]">
        <option value="1">出版社A</option>
        <option value="2">出版社B</option></select><br/>
        
      • リストボックス(複数指定):
        <select id="book_publish" multiple="multiple" name="book[publish][]">
        <option value="出版社A">出版社A</option>
        <option value="出版社B">出版社B</option></select><br/>
        
    • ちなみに、コントローラ側(ここだとcontrollers/books_controller.rbのnewメソッドの@bookの初期化を以下のように修正すれば、初期値設定(selected="selected")ができるよー
         @book = Book.new(:publish => '出版社B' )
      
  • collection_selectは、DBのオブジェクトから値表示!
    • まずは、以下のコードをコントローラ側(ここだとcontrollers/books_controller.rbのnewメソッド)に追加して、データを取得
         @books = Book.select('DISTINCT publish');
      
    • で、View側でこんな感じに書くと
      <%=f.collection_select(
        :publish, # selectのnameの対象
        @books,   # これがDBから取ってきたオブジェクト
        :publish, # valueに割り当てる対象
        :publish  # textに割り当てる対象
      ) %><br/>
      
    • こんな感じで出る
      <select id="book_publish" name="book[publish]">
      <option value="インプレスジャパン">インプレスジャパン</option>
      <option value="技術評論社">技術評論社</option>
      <option value="日経BP社">日経BP社</option>
      <option value="秀和システム">秀和システム</option>
      <option value="翔泳社">翔泳社</option></select><br/>
      
      • これは、booksテーブルの中身ね。
  • grouped_collection_selectは、<optgroup>タグを使ってのリスト作成する!
    • これ、アソシエーションを使うんで、一発でテーブルの関連を考慮してタグを出力してくれるんだ!すげー
    • さすがに例が難しいんで、とりあえずRailsのヘルプへのリンクを書いておくか…
      • きっと、こんな感じかな?
        <%=f.grouped_collection_select(
          :book_id, # selectのnameの対象
          @authors, # DBから取ってきたオブジェクト
          :books,   # <option>タグを取得するメソッド
          :name     # <optgroup>タグのlabel
          :id       # <option>タグのvalue
          :title    # <option>タグのテキスト
        ) %><br/>
        
    • まあ、collection_selectと似てて、更にグループも指定できるって感じかな?
  • 以上は、モデルに関連するメソッドだったけど、モデルと無関係にもリストを作れる
    • select_tagは、全部指定して<select>を生成
    • options_for_selectだとハッシュから生成
    • option_from_collection_selectだと、DBのオブジェクトから生成
    • option_groups_from_collection_selectだと、<optgroup>の生成
    • datetime_select/date_select/time_selectだと、日時指定のリスト生成。え、これすごくない?
      • 例えば日付(date_select)だと、これだけで
        日付:<%= f.date_select :published, :use_month_numbers => true %><br/>
        
      • こう出る
        日付:<select id="book_published_1i" name="book[published(1i)]">
        <option value="2006">2006</option>
        中略
        <option selected="selected" value="2011">2011</option>
        中略
        <option value="2016">2016</option> </select>
        <select id="book_published_2i" name="book[published(2i)]">
        <option value="1">1</option>
        中略
        <option selected="selected" value="11">11</option>
        <option value="12">12</option>
        </select>
        <select id="book_published_3i" name="book[published(3i)]">
        <option value="1">1</option>
        中略
        <option selected="selected" value="12">12</option>
        中略
        <option value="31">31</option>
        </select>
        <br/>
        
      • オプションはいっぱいあるけど、日本語だと最低限「:use_month_numbers => true」くらいはしないと月が「January」とかになるので注意!
      • 当然、日時&時間のみとかもある
        日時:<%= f.datetime_select :published, :use_month_numbers => true %><br/>
        時間:<%= f.time_select :published, :use_month_numbers => true %><br/>
        

その他

  • labelは、国際化対応済みだから、べたで書くより危なくないよ
  • submitは、確認ダイアログとか処理中とかも対応してる!
    • これで、
         <%= f.submit '保存', :confirm => '保存しても良いですか?', :disable_with => '処理中…' %>
      
    • こう
         <input data-confirm="保存しても良いですか?" data-disable-with="処理中…" name="commit" type="submit" value="保存" />
      
    • あ、submitはCreate/Updateを自動判定してるから、ここで指定しちゃうとその機能は無効になっちゃうんだ。
  • fields_forだと、form_for内でも他もモデルも参照可能
    • この時、fields_set_tagとかを使うと、フォームの要素を<fieldset>タグでグループ化できるらしいです。

-
最終更新:2011年12月23日 07:24