Tag: Rails/ビューヘルパー

目次

関連ページ

参考情報

リンク

別ウィンドウで開く

  • targetを指定する
    <%= link_to("外部サイト", 'http://example.com/', target:  '_blank') %>

link_toでfont-awesomeのアイコンを使用する

  • いろいろな方法があるらしいけどrawを使うのが簡単。
    <%= link_to(raw("<i class='fa fa-home' title='配布元'></i>"), 'http://example.com/', target:  '_blank') %>

form

form_for

  • form_forでモデル連携型のフォームが生成できる。
    <%= form_for(@book) do |f| %>
    タイトル: <%= f.text_field(:title, {:size => 40}) %>
    <%= f.submit %>
    <%= end %>
    
  • @bookが保存されているかどうかで、呼ばれるアクションが自動的に変わる。

form_tag

  • form_tagでもモデル連動は可能。
    <%= form_tag({ :controller => 'books', :action => 'create'}) do %>
    タイトル: <%= text_field(:book , :title, {:size => 40}) %>
    <%= f.submit %>
    <% end %>
    

ラベル

f.label

  • プロパティ名と実際に表示する文字列を併記する場合(プロパティ名は対応するコントロールにフォーカスを移すために必要)
    <%= f.label :title, 'タイトル' %>
    

セレクト

tag系とそれ以外で最後のオプションの渡し方がことなるので注意。

f.select

  • 配列から生成。
    <%= f.select(:object_field, ['Item 1', ...], {}, { class: 'my_style_class' }) %>
  • オブジェクトの配列から生成。
     <%= f.select(:category_id, Category.all.map{|category| [category.title, category.id]}, {include_blank: '選択'}, {class: 'form-control'} ) %>

select_tag

  • options_for_selectを使えばオブジェクトの配列から生成することができる。
    select_tag 'xxx', options_for_select(@objects.map{|obj| [obj.title, obj.id]})
    

options_for_select注意点

  • ハッシュを渡してもいいけど、順番が保証されない。
  • 配列の配列を渡すのがいいらしい。
  • もしくはオブジェクトの配列で上のようにmapする。

チェックボックス

f.check_box

  • プロパティ名、HTMLオプション、チェック値、非チェック値の順に渡す。
    f.check_box(accepted:, {class: 'my-checkbox'}, 'yes', 'no');
  • チェックしてないときにnilを渡したい場合、nilを指定する。
    f.check_box(accepted:, {class: 'my-checkbox'}, 'yes', nil);

複数のチェックボックスの値を送信

  • Railsではチェックボックスの名前の後ろに括弧を追加してマークアップすると、サーバー側で配列として取り扱うことができる。
  • 例えば以下のように。
    <%= check_box_tag "todo_ids[]", todo.id %>
  • しかしこのままだと複数存在するinputタグのidが"todo_ids_"で全て同じになってしまう。ajax - How do I set a unique ID for checkboxes in a multi-record Rails form? - Stack Overflow
  • これを回避するためには、:idを明示するしかないかもしれない。
    <%= check_box_tag "todo_ids[]", todo.id, false, :id => "todo_id_#{todo.id}" %>

サブミット

確認メッセージを表示する

  • submit_tagで確認メッセージを表示する。
      <%= submit_tag('削除',  {name: 'delete', class: 'btn btn-danger', data: {confirm: '削除しますか?'} } ) %>
    

hidden

f.hidden_field

  • 通常はプロパティ名のみ
    <%= f.hidden_field(:folder_id) %>
  • 値を指定する場合
    <%= f.hidden_field(:folder_id, value: 9) %>

Bootstrap3との連携

  • twbs/bootstrap-sassを使って、rails4とbootstrap3を連携している場合を考える。

メッセージの表示

  • application_helper.rbに以下を追加
      def bootstrap_class_for flash_type
        { success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }[flash_type.to_sym] || flash_type.to_s
      end
    
      def flash_messages(opts = {})
        flash.each do |msg_type, message|
          concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} alert-dismissible", role: 'alert') do
                   concat(content_tag(:button, class: 'close', data: { dismiss: 'alert' }) do
                            concat content_tag(:span, '&times;'.html_safe, 'aria-hidden' => true)
                            concat content_tag(:span, 'Close', class: 'sr-only')
                          end)
                   concat message
                 end)
        end
        nil
    
  • application.html.erbに以下を追加
    <div class="container">
        <!-- flash message -->
        <%= flash_messages %>
    
        <%= yield %>
    
        <hr>
        <footer>
            <p>&#169; src256</p>
        </footer>
    
    </div>
    
  • controllerで以下のように設定すると、画面の上部にBootstrap風のエラー画面が表示される。
        msg = "保存しました"
        flash[:notice] = msg
        redirect_to(software_path(id, take_params))
    

一覧画面

  • Bootstrap3を使ってテーブルを一覧表示(index.html.erb)
    <h1>アイテム一覧</h1>
    
    <table class="table">
        <tr>
            <th class="col-xs-3">カテゴリ</th>
            <th class="col-xs-3">タイトル</th>
            <th class="col-xs-3">コンテンツ</th>
            <th class="col-xs-3">操作</th>
        </tr>
    
        <% @items.each do |item| %>
            <tr>
                <td><%= item.category_id %></td>
                <td><%= item.title %></td>
                <td><%= item.content %></td>
                <td><%= link_to 'Show', item %></td>
                <td><%= link_to 'Edit', edit_item_path(item) %></td>
                <td><%= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
            </tr>
        <% end %>
    </table>
    
    <br>
    
    <%= link_to 'アイテム追加', new_item_path %>
    
    

追加・編集画面

  • form-horizontalでラベルとコントロールを横に並べる。
  • labelはインライン要素だが"display: inline-block"が指定されているので幅が指定できる(divで囲む必要がない)
  • control-labelを指定すれば、右寄せ垂直方向中心となる。
    <%= form_for(@item, html: {class: 'form-horizontal'}) do |f| %>
        <% if @item.errors.any? %>
            <div id="error_explanation">
                <h2>エラーが発生しました :</h2>
                <ul>
                    <% @item.errors.full_messages.each do |msg| %>
                        <li><%= msg %></li>
                    <% end %>
                </ul>
            </div>
        <% end %>
    
        <div class="form-group">
            <%= f.label(:category_id, 'カテゴリ', class: 'col-xs-2 control-label') %>
            <div class="col-xs-10">
                <%= f.select(:category_id, Category.all.map{|category| [category.title, category.id]}, {include_blank: '選択'}, {class: 'form-control'} ) %>
            </div>
        </div>
        <div class="form-group">
            <%= f.label(:folder_id, 'フォルダ', class: 'col-xs-2 control-label') %>
            <div class="col-xs-10">
                <%= f.select(:folder_id, Folder.all.map{|folder| [folder.title, folder.id]}, {include_blank: '選択'}, {class: 'form-control'} ) %>
            </div>
        </div>
        <div class="form-group">
            <%= f.label(:title, 'タイトル', class: 'col-xs-2 control-label') %>
            <div class="col-xs-10">
                <%= f.text_field(:title, class: 'form-control') %>
            </div>
        </div>
        <div class="form-group">
            <%= f.label(:content, 'コンテンツ', class: 'col-xs-2 control-label') %>
            <div class="col-xs-10">
                <%= f.text_area(:content, rows: 14, cols: 20, class: 'form-control') %>
            </div>
        </div>
        <div class="form-group">
            <div class="col-xs-12">
                <%= f.submit('保存', class: 'btn btn-primary') %>
            </div>
        </div>
    <% end %> 
    

Tips

検索条件を引き回す

  • よくある一覧画面から詳細画面へ遷移するような例を考える。
  • 一覧画面で検索条件が指定されていたりページングによってフィルタリングされている場合、この検索条件を詳細画面にもっていかないと戻ってこれない。
  • » URL パラメータの一部を遷移先に引き継ぐ TECHSCORE BLOGにあるtake_paramsを使うと便利。
      def default_take_param_keys
        %w(page per_page)
      end 
     
     def take_params(*param_keys)
        overwrites = param_keys.extract_options!
        param_keys = default_take_param_keys if param_keys.blank?
        params.dup.extract!(*param_keys).update(overwrites)
      end 
      helper_method :take_params
    
  • オリジナルの記事で紹介されているのは、検索ページから検索条件を詳細画面に引き継ぎ、詳細画面のビュー元の検索画面に戻ってくるような事例。どちらもlink_toでtake_paramsを指定する。これによってparams[:page]やparams[:q]のような情報を簡単に引き継ぐことが可能となる。
  • その他のバリエーションとして詳細画面がフォームになっていて、登録後検索画面に戻るときは、controllerのredirect_toでtake_paramsを指定する。

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-07-27 (金) 13:42:42