複合条件でリスト表示、実際のコード。
以下は、Ajaxを利用して、並び替え、キーワードフィルター、フリーワード検索の複合条件で、リスト表示するための実際のコード。
app/controllers/softwares_controller.rb
- Ajax処理の場合は、list_updateが処理する。その際、@ajax_update変数にtrueを設定する。(list.rhtmlでAjax処理かどうかを判断して、描画内容を変更するため。)
- conditionsの設定にはSQLのLIKE演算子を利用した。
class SoftwaresController < ApplicationController include SoftwaresHelper hide_field :id, :url, :user_id, :only => [:index, :list_update, :list, :list_by_keyword, :list_in_order] hide_field :id, :created_on, :updated_on, :user_id, :only => [:new, :confirm_create, :create, :edit, :onfirm_update, :update] ...(途中省略)... def set_pagination #パラメーターを取得 @keyword_id = params[:keyword_id] || params[:store_keyword_id] || "%" @order_field = params[:order_field] || params[:store_order_field] || "id" @order_direction = params[:order_direction] || params[:store_order_direction] || "ASC" @search_word = params[:store_search_word] #条件によって、パラメーターを変更 @keyword_id = "%" if params[:keyword_id] == params[:store_keyword_id] @order_direction = 'ASC' if params[:order_field] && !(params[:order_field] == params[:store_order_field]) @direction_mark = @order_direction == 'DESC' ? '▼' : '▲' @order_next_direction = @order_direction == 'DESC' ? 'ASC' : 'DESC' #paginate処理 conditions = ["keyword_id LIKE ? AND (title LIKE ? OR description LIKE ?)", @keyword_id ,"%#{@search_word}%" ,"%#{@search_word}%" ] order = "#{@order_field} #{@order_direction}" @software_pages, @softwares = paginate :softwares, :per_page => 4, :conditions => conditions, :order => order end def list_update Software.with_scope(login_user) do @ajax_update = true # Ajax処理であることを示す。 set_pagination # :layout => falseで、レイアウトテンプレートsoftwares.rhtmlを利用しないで描画する。 render :action => "list", :layout => false end end def list Software.with_scope(login_user) do set_pagination end end ...(途中省略)...
app/views/softwares/list.rhtml
<%# listメソッドから描画する場合は、Ajaxで更新する部分list_updateを<div>タグで指定でする。 %> <% unless @ajax_update %> <div id="list_update"> <% end %> <%# list_updateメソッドから描画する場合は、スタイルシートを適用する。 %> <% if @ajax_update %> <head> <%= stylesheet_link_tag 'scaffold' %> </head> <% end %> <h1><%= localize(:model, :software) %><%= localize(:title, :list) %></h1> <div class="indent"> <%= localized_error_messages_for 'software' %> <table class="confirm"> <%# リストをフォーム、ヘッダー、データ部分に分けて描画する。 %> <%= render :partial => 'models/softwares/list_form' %> <%= render :partial => 'models/softwares/listh' %> <%= render :partial => 'models/softwares/listd', :collection => @softwares %> <%# link_to_remoteによる、前ページ<< >>次ページ %> <tr><th colspan="6"> <%= link_to_remote "#{localize(:label, 'Previous page')} << ", :update => "list_update", :submit => "store", :url => { :action => 'list_update', :page => @software_pages.current.previous } if @software_pages.current.previous %> <%# pagination_linksについては、Ajaxに対応させることが出来なかったので、とりあえずコメントアウト。 %> <%#= pagination_links @software_pages %> <%= link_to_remote " >> #{localize(:label, 'Next page')}", :update => "list_update", :submit => "store", :url => { :action => 'list_update', :page => @software_pages.current.next } if @software_pages.current.next %> </th></tr> </table> <br /> <%= link_to localize(:label, :new), :action => 'new' %> </div> <%# listメソッドから描画する場合の、終了タグ。2-4行目に対応。 %> <% unless @ajax_update %> </div> <% end %>
app/views/models/softwares/_list_form.rhtml
<%# フォームを送信するブロックを指定 %> <div id="store"> <%# returnキーでフォームをAjax送信する。 %> <%= form_remote_tag :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %> <%= link_to 'リセット', :action => 'list' unless @keyword_id.nil? && @order_field.empty? %> <span style="font-weight:bold;"> <%= human_attribute_name(Software, "title") %>/<%= human_attribute_name(Software, "description") %> </span>を検索 : <%= text_field_tag("store_search_word", @search_word) %> <%# 「検索」ボタン、フォームをAjax送信する。 %> <%= submit_to_remote "store", "検索", :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %> <%# 「クリア」リンク、フォームをAjax送信する。 %> <small> <%= link_to_remote "クリア", :update => "list_update", :submit => "store", :url => {:action => 'list_update', :store_search_word => ""} %> </small> <%# 設定値を保持するためのフォーム %> <%= hidden_field_tag("store_order_field", @order_field) %> <%= hidden_field_tag("store_order_direction", @order_direction) %> <%= hidden_field_tag("store_keyword_id", @keyword_id) %> <%= end_form_tag %> </div>
app/views/models/softwares/_listh.rhtml
<!--[:]--> <tr> <% for column in Software.columns %> <% unless @controller.class.hidden_field?(@action_name, column.name) %> <%# 列タイトルをクリックした時の並べ替えをAjaxで処理する。 %> <th><%= link_to_remote "#{@direction_mark if @order_field==column.name}#{human_attribute_name(Software, column.name)}", :update => "list_update", :submit => "store", :url => {:action => 'list_update', :order_field => column.name, :order_direction => @order_next_direction} %></th> <% end %> <% end %> <th><br></th> </tr> <!--[:]-->
app/views/models/softwares/_listd.rhtml
...(途中省略)... <%- unless @controller.class.hidden_field?(@action_name, 'keyword_id') -%> <%# キーワードのフィルタリングをAjaxで処理する。 %> <td width="16%"><%= link_to_remote h(listd.keyword.name), :update => "list_update", :submit => "store", :url => {:action => 'list_update', :keyword_id => listd.keyword_id} %></td> <%- end -%> ...(途中省略)...
現在、pagination_linksをAjax処理に対応できない状態だ。その方法はHow to Paginate With Ajaxがとても参考になりそう。複合条件を保持するためには、ページ番号をクリックした時にも、link_to_remoteのようにフォームデータを送信する必要がある。そうだ、pagination_links_remoteが欲しい!