Ruby on Rails gem "acts_as_list" を使用した項目の並び替え実装

gem "acts_as_list"を使用して一覧表示などをしている項目の並び替えを実装します。各項目ごとにに”↑”、”↓”を表示させてそれぞれ1つ上、1つ下に移動するようにします。
ダミーデータ生成にはgem "gimei" を使用します。

参考サイト
【Rails5】acts_as_listでデータの並び替え機能を実装 - Railsからはじめるプログラミング日記
acts_as_listの使い方 – ABC Blog

gemの準備

scaffoldでUserを生成.

$ rails generate scaffold User name:string address:string

Gemfileに以下を追加しbundle install.

gem 'acts_as_list'
gem 'gimei'

positionカラムの追加

"acts_as_list"はpositionカラムを使用することが決まっているので以下で"position"を追加.

$ rails generate migration AddPositionToUser position:integer
$ rails db:migrate

コンソールで確認するとカラムは以下."position"カラムが追加されている.

>> User.column_names
=> ["id", "name", "address", "created_at", "updated_at", "position"]

ダミーデータの生成

今回はgem "gimei"を使用してダミーデータを用意します。

以下サイトを参考にさせていただきました。
【Rails】gem 'gimei' で日本語のダミーデータを生成する | RemoNote

[db/seeds.rb]を以下のように編集

50.times do |pos|
  gimei = Gimei.new
  
  User.create(
    name: gimei.name.kanji,
    address: gimei.address.prefecture.kanji,
    position: pos
  )
end

"rails db:seed" を実行し反映させるとダミーデータが生成される。

対象modelの編集

[app/models/user.rb]Userモデルに以下の一文を追加

class User < ApplicationRecord
    acts_as_list #追加
end

actionの設定

[/app/contollers/user_controller.rb] indexアクションの編集およびmove_higher, move_lowerの新規追加を行う.

  def index
    @users = User.all.order(:position) #positionカラムに従いソート
  end
  
  def move_higher
    User.find(params[:id]).move_higher
    redirect_to :action => :index
  end
 
  def move_lower
    User.find(params[:id]).move_lower
    redirect_to :action => :index    
  end

ルーティングの設定

追加したaction達のルーティング設定
[/Book/config/routes.rb]

Rails.application.routes.draw do
  resources :users do
    member do
      get :move_higher
      get :move_lower
    end
  end
end

viewの編集

最後に上下移動用のリンクをビューに設定して完了.
[/app/views/users/index.html.erb]

  <tbody>
    <% @users.each do |user| %>
      <tr>
        <td><%= link_to "", {:controller => :users, :action => :move_higher, :id => user} %></td>
        <td><%= link_to "↓", {:controller => :users, :action => :move_lower, :id => user} %></td>  
        <td><%= user.name %></td>
        <td><%= user.address %></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>

最終画面

こんな感じで上下の矢印をクリックすると移動.

f:id:Kurorera:20190507115305p:plain
before move
↓を押すと
f:id:Kurorera:20190507115410p:plain
after move