これは何
1画面に複数モデルを表示するSPAっぽいRailsアプリで画面遷移無しで追加読み込みしたい、
でもReactやAngular はよく分からない を導入してる時間はない、
という人のための記事です。
GitHubに作成済みのソースコードがあります。
何を使うの
kaminariとjQuery, jquery.infinitscrollを使いモデルの追加読み込みを実装します。
どうなるの
どうするの
アプリの作成
コマンド
$ rails new multi-model-infinitscroll --skip-bundle &&
cd multi-model-infinitscroll
下拵え
kaminariとjquery-turbolinksのインストール
Gemfile
# 追記
gem "jquery-turbolinks"
gem "kaminari"
コマンド
$ bundle install
jquery.infinitscrollのダウンロード
コマンド
$ curl -k -o vendor/assets/javascripts/jquery.infinitescroll.js \
https://raw.githubusercontent.com/paulirish/infinite-scroll/master/jquery.infinitescroll.js
Asset Pipelineにjquery-turbolinksとjquery.infinitscrollを追加
app/assets/javascripts/application.js
# 追記
//= require jquery.turbolinks
//= require jquery.infinitescroll
モデルの準備
モデルの作成
コマンド
$ rails g model Hoge name description &&
rails g model Piyo name description &&
rails db:migrate
初期データの投入
db/seeds.rb
# 追記
1000.times do |i|
Hoge.create!(name: 'Hoge' + i.to_s, description: 'This is Hoge ' + i.to_s)
Piyo.create!(name: 'Piyo' + i.to_s, description: 'This is Piyo ' + i.to_s)
end
コマンド
$ rails db:seed
Controllerの準備
メイン画面となるControllerを作成
コマンド
$ rails g controller home home
app/controllers/home_controller.rb
class HomeController < ApplicationController
def home
#下記追記
#普通のアクセスの時に実行
@hoges = Hoge.page(params[:hoge_page]) if params[:piyo_page].blank?
@piyos = Piyo.page(params[:piyo_page]) if params[:hoge_page].blank?
#*_pageが渡された時はもう片方は不要なのでif文でDBへのアクセスを軽減
#追加読み込み時に実行、レイアウト無しでデータのみを返す
unless params[:hoge_page].blank?
return render @hoges, layout: false
end
unless params[:piyo_page].blank?
return render @piyos, layout: false
end
end
end
ルーティングの設定
config/routes.rb
Rails.application.routes.draw do
get 'home/home' #要らないので任意で削除
root to: 'home#home' #追記
end
モデル読み込み用のControllerを作成
これはなくても動くので任意で作成してください。
コマンド
$ rails g controller hoges &&
rails g controller piyos
Viewの準備
home viewの編集
app/views/home/home.html.erb
<div id='hoge_container'>
<table id="hoges">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody class="page">
<%= render @hoges %>
</tbody>
</table>
<br>
<%= paginate @hoges, remote: true, param_name: :hoge_page %>
</div>
<div id='piyo_container'>
<table id="piyos">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody class="page">
<%= render @piyos %>
</tbody>
</table>
<br>
<%= paginate @piyos, remote: true, param_name: :piyo_page %>
</div>
hogeテンプレートの作成
app/views/hoge/_hoge.html.erb
<tr class="hoge">
<td><%= hoge.name %></td>
<td><%= hoge.description %></td>
</tr>
piyoテンプレートの作成
app/views/piyo/_piyo.html.erb
<tr class="piyo">
<td><%= piyo.name %></td>
<td><%= piyo.description %></td>
</tr>
cssの編集
app/assets/stylesheets/application.css
/*追記*/
# infscr-loading, .pagination {
width: 0;
display: none;
}
# hoge_container, #piyo_container{
float: left;
margin: 10px 50px;
padding: 10px 50px;
}
thead, tbody {
display:block;
}
tbody {
overflow-y:scroll;
height:500px;
}
infinitescrollの設定
behaviorsとbinderを指定する事でウィンドウではなく特定の要素が下までスクロールされた時に追加読み込みを実行します。
app/assets/javascripts/home.coffee
# 追記
$ ->
$("#hoges .page").infinitescroll
loading: {
img: ""
msgText: ""
finishedMsg: ""
}
animate: true
navSelector: "#hoge_container nav.pagination"
nextSelector: "#hoge_container nav.pagination a[rel=next]"
itemSelector: "tr.hoge"
behaviors: "local"
binder: $("#hoge_container .page")
$ ->
$("#piyos .page").infinitescroll
loading: {
img: ""
msgText: ""
finishedMsg: ""
}
animate: true
navSelector: "#piyo_container nav.pagination"
nextSelector: "#piyo_container nav.pagination a[rel=next]"
itemSelector: "tr.piyo"
behaviors: "local"
binder: $("#piyo_container .page")
実行
コマンド
$ rails s
localhost:3000/にアクセスして動作を確認してみてください。
それぞれをスクロールして自動で追加読み込みされれば成功です。
まとめ
JavaScriptフレームワークを勉強しましょう。