導入
Gemfile
gem 'acts_as_list'
$ bundle install
app/models/task.rb
class Task < ApplicationRecord
acts_as_list
end
rails g migration AddPositionToTask position:integer
class AddPositionToTask < ActiveRecord::Migration[6.0]
def change
add_column :tasks, :position, :integer #カラム名はpositionじゃなきゃいけない
end
end
$ rails db:migrate
config/routes.rb
resources :tasks do
member do
get :move_higher
get :move_lower
end
end
同期処理で動かす
app/contollers/tasks_controller.rb
def index
@tasks = Task.all.order(:position) # positionカラムに従いソート
end
def move_higher
Task.find(params[:id]).move_higher #move_higherメソッドでpositionを上に
redirect_to action: :index
end
def move_lower
Task.find(params[:id]).move_lower #move_lowerメソッドでpositionを下に
redirect_to action: :index
end
app/views/tasks/index.html.erb
<h2>タスク一覧</h2>
<table>
<% @tasks.each do |task| %>
<tr>
<td><%= task.name %></td>
<td><%= link_to '詳細', user %></td>
<td><%= link_to "↑", move_higher_task_path(task) %></td>
<td><%= link_to "↓", move_lower_task_path(task) %></td>
</tr>
<% end %>
</table>
非同期処理で動かす
app/contollers/tasks_controller.rb
def index
@tasks = Task.all.order(:position)
end
def move_higher
@task = Task.find(params[:id])
@task.move_higher
@tasks = Task.all.order(:position)
end
def move_lower
@task = Task.find(params[:id])
@task.move_lower
@tasks = Task.all.order(:position)
end
app/views/tasks/index.html.erb
<div id='task-list'>
<table>
<% @tasks.each do |task| %>
<tr class='body-row'>
<td><%= task.name %></td>
<td><%= link_to '詳細', task %></td>
<td><%= link_to '↑', tasks_path(task), remote: true %></td>
<td><%= link_to '↓', tasks_path(task), remote: true %></td>
</tr>
<% end %>
</table>
</div>
app/views/_tasks.html.erb
<table>
<% tasks.each do |task| %>
<tr class='body-row'>
<td><%= task.name %></td>
<td><%= link_to '詳細', task %></td>
<td><%= link_to '↑', tasks_path(task), remote: true %></td>
<td><%= link_to '↓', tasks_path(task), remote: true %></td>
</tr>
<% end %>
</table>
app/views/move_higher.js.erb
$('#task-list').html("<%= j(render 'tasks/tasks', tasks: @tasks) %>");
app/views/move_lower.js.erb
$('#task-list').html("<%= j(render 'tasks/tasks', tasks: @tasks) %>");
scope
taskテーブルのkindカラムの中で並び替えをしたい場合(kindで絞り込みをした状態でもうまく動くようにしたい場合)、以下のように書く。
app/models/task.rb
class Task < ApplicationRecord
acts_as_list scope: [:kind]
end
注意点
positionカラムのデータがnullだと動かない。
既存のテーブルに後からpositionカラムを追加した際には、なんらかの方法で全てのデータのpositionカラムに数値を入力する必要がある。