#はじめに
- railsアプリでgem "kamianri"を用いて、ページネーション機能を実装してみようと思います。
- 今回使ったアプリ→https://github.com/shotaimai66/users
#想定機能
- ユーザー一覧(index)を表示するページの実装
- ユーザーの表示数は3人で設定
- 同期処理、非同期処理両方実装
#環境
- AWScloud9
- Rails 5.2.2
- ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
- gem "kamianri"
#実装 (同期処理)
###前提
ユーザーの一覧ページはできているものとします。以下画像。
###gem "kamianri" インストール
Gemfile
gem 'kaminari'
コマンド
bundle install
###コントローラー修正
app/controllers/users_controller.rb
def index
@users = User.page(params[:page]).per(3).all
end
###ビュー修正
app/views/users/index.html.erb
<div id="pagenate">
<p id="notice"><%= notice %></p>
<h1>Users</h1>
<h3>ユーザー数:<%= @users.size %></h3>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>名前</th>
<th>年齢</th>
<th>性別</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= user.name %></td>
<td><%= user.age %></td>
<td><%= user.sex %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate @users %>
<br>
</div>
<%= link_to 'New User', new_user_path %>
###同期処理完成
- 同期処理でのページネーションはめっちゃ簡単ですね。gemの力は絶大です。ですが、頼りすぎは禁物ですね。
#実装(非同期処理)
###コントローラー修正
app/controllers/users_controller.rb
def index
@users = User.page(params[:page]).per(3).all
respond_to do |format|
format.html
format.js
end
end
- コントローラーのindexアクションで最後に
format.js
が評価され、jsフォーマットが返される。そして、index.js.erb
を探しに行きます
###JSビュー作成
app/views/users/index.js.erb
$('#pagenate').html("<%= escape_javascript(render 'index_page') %>");
- index.js.erbでは、htmlメソッドで
<%=render 'index_page'%>
をidがpagenateのdiv要素にレタリングされます。 - 次にパーシャルの
_index_page.html.erb
を作成します。
###パーシャル作成
app/views/users/_index_page.html.erb
<p id="notice"><%= notice %></p>
<h1>Users</h1>
<h3>ユーザー数:<%= @users.size %></h3>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>名前</th>
<th>年齢</th>
<th>性別</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= user.name %></td>
<td><%= user.age %></td>
<td><%= user.sex %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate @users, remote: true %>
<br>
###index.html.erb修正
app/views/users/index.html.erb
上記省略
</table>
##以下のerbに`remote: true`を追記
<%= paginate @users, remote: true %>
<br>
</div>
<%= link_to 'New User', new_user_path %>
-
<%= paginate @users, remote: true %>
とすることで非同期で処理をするという命令になります。
#解説
##respond_to do |format|~end
- indexアクションの
respond_to 〜ブロック〜
では、指定されたフォーマット形式で@userの情報を返しています。例えば以下のように、indexアクションを修正すると、/users.json
にアクセスすると以下のような情報が得られます。
app/controllers/users_controller.rb
def index
@users = User.all.page(params[:page]).per(3)
respond_to do |format|
format.html
format.js
format.json { render :json => @users }
format.xml { render :xml => @users }
end
end
-
/users.xml
にアクセスすると以下のようにXML形式の@usersの情報が得られます。
- 同じようにhtml、jsも情報を送っている。jsに限っては,アクセスしてもエラーになってしまいます。
- 作成した機能を例にとれば、実際の非同期の流れは、
index.html.erb→
indexアクション→``index.js.erb→``_index.page.html.erb
という感じになります。
##index.js.erb
app/views/users/index.js.erb
$('#pagenate').html("<%= escape_javascript(render 'index_page') %>");
- 上のjsコードは
idがpagenateの要素に、htmlメソッドを使って、 <%= render 'index_page' %>
を挿入するという意味です。 - htmlメソッドは、任意の要素に指定した、htmlを挿入するjavascriptのメソッドです。
- escape_javascriptは、javascriptのエスケープメソッドですね。jsコードの中では、erb文は直接かけないので、こういう書き方になります。
#まとめ
少し長くなりましたが、ほんとに簡単にできました。
さらに便利なkaminariメソッド群は公式へ→https://github.com/kaminari/kaminari