目標
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina
前提
下記実装済み。
実装
1.Gemを導入
# 追記
gem 'jquery-ui-rails'
gem 'ranked-model'
jquery-ui-rails
➡︎ jQuery UIを使用出来るようにする。
gem 'ranked-model'
➡︎ Bookの並び順を管理出来るようにする。
3.カラムを追加
$ rails g migration AddRowOrderToBooks row_order:integer
$ bundle
create_table "books", force: :cascade do |t|
t.integer "user_id"
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "row_order"
end
4.モデルを編集
Bookモデルでranked-model
を使えるようにする。
# 追記
include RankedModel
ranks :row_order
5.コントローラーを編集
①indexアクション
を編集
# 変更前
@books = Book.all
# 変更後
@books = Book.rank(:row_order)
②ストロングパラメーターにrow_order_position
を追加する。
カラム名はrow_order
だが、ここではGemの使用上row_order_position
と記述する。
def book_params
params.require(:book).permit(:title, :body, :row_order_position)
end
③sortアクション
を追加
def sort
book = Book.find(params[:book_id])
book.update(book_params)
render body: nil
end
render body: nil
➡︎ アクションだけを実行し、ビューは呼び出さない。
6.ルーティングを編集
# 変更前
resources :books
# 変更後
resources :books do
put :sort
end
7.ビューを編集
/ 「table-sortable」というクラスを付与
table.table.table-bordered.table-sortable
thead
tr
th
| 投稿者
th
| タイトル
th
| 本文
th
tbody
- @books.each do |book|
/ trタグにクラスを付与し、データを設定する
tr.item(data = { model_name: book.class.name.underscore, update_url: book_sort_path(book) })
td
= link_to book.user do
= book.user.name
td
= link_to book.title, book_path(book)
td
= book.body
td
-if book.user == current_user
= link_to '削除', book, method: :delete, data: { confirm: '本当に削除してもよろしいですか?' }, class: 'btn-sm btn-danger'
model_name: book.class.name.underscore
➡︎ 「book」はeach分のブロック変数にあたる。
8.application.js
を編集
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require jquery
//= require jquery-ui/widgets/sortable // 追記
//= require jquery-ui/effects/effect-highlight // 追記
//= require bootstrap-sprockets
//= require_tree .
//= require jquery-ui/widgets/sortable
➡︎ jQuery UIを有効化
//= require jquery-ui/effects/effect-highlight
➡︎ ドラッグ&ドロップ時のエフェクトを有効化
9.JavaScriptファイルを作成・編集
$ touch app/assets/javascripts/table_sort.js
$(function(){
$('.table-sortable').sortable({
axis: 'y',
items: '.item',
// Ajaxで並び順のデータをコントローラーに送信
update(e, ui) {
let item = ui.item;
let item_data = item.data();
let params = { _method: 'put' };
params[item_data.model_name] = { row_order_position: item.index() };
$.ajax({
type: 'POST',
url: item_data.update_url,
dataType: 'json',
data: params,
});
},
// ドラッグ幅をテーブルに合わせる
start(e, ui) {
let cells, tableWidth, widthForEachCell;
tableWidth = $(this).width();
cells = ui.item.children('td');
widthForEachCell = tableWidth / cells.length + 'px';
return cells.css('width', widthForEachCell);
},
// エフェクトを付与
stop(e, ui) {
return ui.item.children('td').effect('highlight');
},
});
});
10.カーソルのデザインを変更
// 追記
.table-sortable {
tr.item {
cursor: row-resize;
}
}