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

Rails Webook

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

RailsでInfinite Scrollとkaminariを使いスクロールによる動的にページロード機能を実装する

Rails gem UI/UX

infinite scrollとは

infinite scrollとは、TwitterやFacebookのようにページの下までスクロールしたら、動的により下のコンテンツが表示されるようにするjQueryプラグインです。

f:id:nipe880324:20141108221903p:plain:w320

動作確認環境

  • Ruby 2.1.0
  • Rails 4.1
  • kaminari 0.16.1
  • infinite scroll 2.0.2

目次

  1. Railsプロジェクトの作成
  2. スクロールによる動的ページロードの実装


1. Railsプロジェクトの作成

まずはRailsプロジェクトを作成します。

rails new infinite_scrolling_kaminari_test
cd infinite_scrolling_kaminari_test

次にInfinite Scrollの挙動を確認するために、ShopをScaffoldで作成します。

rails g scaffold Shop name zipcode address tel

データをseeds.rbに記載します。

# db/seeds.rb

1000.times do |i|
  Shop.create!(
    name:    "店名#{i}",
    zipcode: "111-#{sprintf("%04d", i)}",
    address: "住所#{i}",
    tel:     "00-1234-#{sprintf("%04d", i)}"
  )
end

マイグレーションを実行し、データを投入します。

rake db:migrate
rake db:seed


では、rails sでサーバーを起動してみましょう。
縦になが〜くデータが1000件表示されていると思います。
f:id:nipe880324:20141108210935p:plain:w320



2. スクロールによる動的ページロードの実装

Gemfileにkaminariを追加します

# Gemfile

gem "jquery-turbolinks" # Turbolinksで遷移したときもjQuery.ready()を呼び出してくれる
gem "kaminari"

そして、Bundlerでgemをインストールします。

bundle install

infinitescroll.jsをGitHubのmasterから取得します。

curl -k -o vendor/assets/javascripts/jquery.infinitescroll.js https://raw.githubusercontent.com/paulirish/infinite-scroll/master/jquery.infinitescroll.js

application.jsにjquery.infinitescrollを追加します。

# app/assets/javascripts/application.js

...
//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require jquery.infinitescroll
//= require turbolinks
//= require_tree .

コントローラーのindexアクションを次のように変え、ページ単位で取得するようにします。
params[:page]にはページ番号が入っているので、kaminariは自動的にオフセットを計算して値を取得してくれます。

# app/controllers/shops_controller.rb

  def index
    @shops = Shop.page(params[:page])
  end

ページネーションを一覧画面の一番下に追加します。
また、データを表示している箇所を部分テンプレートにするため、renderに書き換えます。
また、id="shops"class="page"をjsで使うので忘れないでください。

# app/views/shops/index.html.erb

<h1>Listing shops</h1>

<!-- 修正箇所 開始 -->
<table id="shops">
<!-- 修正箇所 終了 -->
  <thead>
    <tr>
      <th>Name</th>
      <th>Zipcode</th>
      <th>Address</th>
      <th>Tel</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <!-- 修正箇所 開始 -->
  <tbody class="page">
    <%= render @shops %>
  </tbody>
  <!-- 修正箇所 終了 -->
</table>

<br>

<%= link_to 'New Shop', new_shop_path %>

<!--一番下に追加 -->
<%= paginate @shops %>

部分テンプレートを作成します。

# app/views/shops/_shop.html.erb

<!-- class="shop" は重要なので忘れないように -->
<tr class="shop">
  <td><%= shop.name %></td>
  <td><%= shop.zipcode %></td>
  <td><%= shop.address %></td>
  <td><%= shop.tel %></td>
  <td><%= link_to 'Show', shop %></td>
  <td><%= link_to 'Edit', edit_shop_path(shop) %></td>
  <td><%= link_to 'Destroy', shop, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>

そして、JavaScriptリクエストのために、部分テンプレートをappendするビューを記載します。

# app/views/shops/index.js.erb

$("#shops").append("<tbody class='page'><%= escape_javascript(render(@posts)) %></tbody>");


そして、最後にinitial scrollで動的にページをロードするJavaScriptを記載します。

$ ->
  $("#shops .page").infinitescroll
    loading: {
      img:     "http://www.mytreedb.com/uploads/mytreedb/loader/ajax_loader_blue_48.gif"
      msgText: "ロード中..."
    }
    navSelector: "nav.pagination" # selector for the paged navigation (it will be hidden)
    nextSelector: "nav.pagination a[rel=next]" # selector for the NEXT link (to page 2)
    itemSelector: "#shops tr.shop" # selector for all items you'll retrieve


ではサーバーを起動して、一覧画面を下にスクロールしましょう。
すると、動的に画面が表示されます。
f:id:nipe880324:20141108221903p:plain:w320


以上です。