【Rails5】acts_as_listでデータの並び替え機能を実装
一覧ページ(index)でよく使いたくなるデータの並び替え機能について
Gemをインストール
acts_as_listというgemを使います。
Gemfileに記載してbundle installしましょう。
【Gemfile】
gem 'acts_as_list'
並べ替えしたいデータのモデルを編集
Userモデルで実装するとしましょう。
userモデルに「acth_as_list」の1行を追加。
【models/user.rb】
class User < ApplicationRecord acts_as_list end
これでデータの作成時にpositionカラムにデータが入るようになります。
※注意!Userテーブルのカラムにpositionがないと動きません、ない場合はrails g migrationで付け加えてください
moveアクションの追加
アクション名はなんでもいいんですが(例えばchange_positionとか)、今回はmoveで。
users_controllerにmoveアクションを定義します。
indexの@userを作る箇所ではpositionでオーダーかける必要があります。
【controllers/users_controller.rb】
class UsersController < ApplicationController def index @user = User.all.order(:position) end def move case params[:move] when 'up' @user.move_higher @target = @user.lower_item when 'down' @user.move_lower @target = @user.higher_item else return head :ok end end end
moveアクションを見ると、params[:move]が飛んでくることがわかりますので、この後viewで飛ばすように実装します。
params[:move]の値がupならmove_higherで上に移動、downならmove_lowerで下に移動をしていますね。
アクション定義したのでroutesに追記
新規アクションを設定したのでroutesを変更しましょう。
【routes.rb】
Rails.application.routes.draw do resources :users do member do get :move end end end
viewの編集
設定が終わったのでviewを作っていきます。
index.html.erbでユーザ一覧を確認できるようにテーブル組みで作成。
左端にはpositionの入れ替えをするlink_toを用意します。
【users/index.html.erb】
<table class="list_table mb_l"> <tr> <th colspan="2"></th> <th><%=f User, :name %></th> <th><%=f User, :email %></th> <th><%=f User, :created_at %></th> <th></th> </tr> <% @users.each do |user| %> <tr> <td><%= link_to '▲', move__user_path(id: user, move: 'up'), remote: true unless user.first? %></td> <td><%= link_to '▼', move_user_path(id: user, move: 'down'), remote: true unless user.last? %></td> <td><%= user.name %></td> <td><%= user.email %></td> <td><%=l user.created_at, format: :long %></td> <td><%= link_to t('link.delete'), user_path(user), method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </table>
@usersをeachで回したtrを入れ替えたいので部分テンプレートにします。
【users/index.html.erb】
<table class="list_table mb_l"> <tr> <th colspan="2"></th> <th><%=f User, :name %></th> <th><%=f User, :email %></th> <th><%=f User, :created_at %></th> <th></th> </tr> <% @users.each do |user| %> <%= render 'user_list', user: user %> <% end %> </table>
部分テンプレートではpositionの変更をした後に表示を切り替えるjsのトリガーを追記します。
また、jsで選択できるようにtrにidを付けておきます。
【users/_users_list.html.erb】
<tr id="user_<%= user.position %>" > <td><%= link_to '▲', move__user_path(id: user, move: 'up'), remote: true unless user.first? %></td> <td><%= link_to '▼', move_user_path(id: user, move: 'down'), remote: true unless user.last? %></td> <td><%= user.name %></td> <td><%= user.email %></td> <td><%=l user.created_at, format: :long %></td> <td><%= link_to t('link.delete'), user_path(user), method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr>
表示の切替を行うjsを作成
viewの▼のリンクにremote: trueを付けました、クリックされたら呼ばれるjsを実装していきます。
まずはusers/move.coffeeファイルを作成。
その後一覧ページの表示切替の処理を記載します。
【users/move.coffee】
$("#user_<%= @user.position %>").replaceWith('<%=j render "user_list", user: @user %>') $("#user_<%= @target.position %>").replaceWith('<%=j render "user_list", user: @target %>')
これで実装完了!
まとめ
慣れれば簡単に実装できますが、変更するファイルが多いのとcoffeeファイルを使うので初心者の方は難しく感じると思います(私もそうでした)。
ruby、railsを覚えてくると何をやっているかわかるようになるはず!
業務では設定の管理ページなどでよく使っています。