やればできる子!will_paginateで動的「もっと見る」を実装
「will_paginate」についてググっていると、「kaminariの方が使いやすい」「will_paginateはデザインが(ry」などの否定的な意見をよく目にします。
そういう時私は、
何がkaminariだよ!!使えるもんなら使いたいわ!!大人の事情ってもんがあるんだ!!
って思う訳です。
今回の「もっと見る」の実装でも、kaminariの情報ばかり出てきて苦労したので火を噴くかと思いました。
早速やってみます。
今回の条件
- ruby:ruby 1.9.3p547 (2014-05-14 revision 45962) [x86_64-linux]
↑大人の事情で古い。。。 - rails:Rails 3.1.7
↑大人の事情で(ry - モデル:article.rb
- コントローラー:portal_controller.rb
- データ:articlesテーブルに6件
コントローラーでやること
portal_controller.rb
indexアクションにpaginate設定します。
def index @items = Article.paginate(:page => params[:page], :per_page => 2) end
データが6件しかないので、
per_page
は2にしてます。moreアクションに「もっと見る」リンクが押された時の処理を書きます。
def more index end
と言っても、ただindexアクションに回すだけです。
この仕組みを使えば大人の事情があって、searchアクションとかの、indexアクション以外からも呼び出されるよって時は、
paramsにアクション名を持たせて、moreアクションからそのアクションを呼び出すようにできます。
ビューでやること
index.html.erb
@itemsを表示する 部分テンプレートを呼び出します。
<div id="items"><%= render 'items' %></div>
タグにidを付けるのが大事!
「もっと見る」リンクを表示する 部分テンプレートを呼び出します。
<%= render 'more' %>
_items.html.erb
データを表示します。
<% @items.each do |item| %> <div> <%= item.title %> <%= item.body %> </div> <% end %>
_more.html.erb
「もっと見る」リンクを表示します。
<% if @items.next_page %> <%= link_to "もっと見る", {:action=>"more", :page => @items.next_page}, :remote => true, id: 'more_link', :onclick => "nowLoading();" %> <% end %>
タグにidを付けるのが大事!
以下ポイント!<% if @items.next_page %>
を使って、次のページ(データ)がある時だけ「もっと見る」リンクを表示するようにします。:page => @items.next_page
でparamsに次のページの番号を渡します。:remote => true
を指定してAjaxで動的処理をします。:onclick => "nowLoading();"
でクリック時にリンクを切るjs関数を呼び出します。(後述します。)
more.js.erb
<div id="items"></div>
に、@itemsを表示する部分テンプレートを追加します。jQuery('#items').append("<%= escape_javascript(render 'items', object: @items) %>");
「もっと見る」リンクを置き直します。
jQuery("#more_link").replaceWith("<%= escape_javascript(render 'more') %>");
ルーティングでやること
routes.rb
indexアクションと、moreアクションを登録します。
controller :portal do get "index" => :index get "more" => :more end
やり方はお任せ。
jsでやること
「もっと見る」リンクをクリックされたら、リンクを外します。
function nowLoading(){ $("#more_link").replaceWith("<a id='more_link'>読込中</a>"); };
これをやらないと、複数回クリックをした時に同じデータが何個も出てきてしまいます。大事!
「読込中」とかにするとお洒落かも。
完成!
実際に使ってみたのがこちら↓
will_paginateさんはYDKでした。