はじめに
以下の記事を参考に、Stimulusを使ってドラッグアンドドロップでの並び替え機能実装を学びました。
https://maful.web.id/posts/build-drag-and-drop-with-rails-hotwire/
その際詰まったり、理解が難しかったことをまとめておきます。
並び替え機能実装の要点
まず、並び替え機能を実現するには(Rails7以前からも存在していた)ranked-model
というgemが必要です。
ranked-modelとは
並び順を持つモデルインスタンスを作る際に必要な機能を提供してくれるgemです。
使い方
必要なカラムをモデルに追加します。
rails g migration AddRowOrderToDucks row_order:integer
rails db:migrate
以下のようにモデルにincludeして使います。並び順に必要なカラムも指定します。
class Duck < ActiveRecord::Base
include RankedModel
ranks :row_order
end
並び順の変更は以下のように行います。
@duck.update row_order_position: 0
非同期で並び替えたい時は、以下のようなajaxリクエストを期待しています。
$.ajax({
type: 'PUT',
url: '/ducks',
dataType: 'json',
data: { duck: { row_order_position: 0 } }, // or whatever your new position is
});
このようなリクエストを、Stimulusから送る形にすれば良いということです。
@rails/request.jsとは
Ruby on Rails 7で導入されたJavaScriptライブラリの一つで、AJAXリクエストを簡単に行うための機能を提供します。このライブラリは、Railsアプリケーションで必要とされるヘッダー(例えば、X-CSRF-Token)をデフォルトで送信するロジックをカプセル化しています。これにより、JavaScriptでのAJAXリクエストの作成をシンプルにできます。
stimulusのコントローラでは以下のようにリクエストを書いています。
onEnd(evt) {
const body = { row_order_position: evt.newIndex }
patch(evt.item.dataset.sortableUrl, {
body: JSON.stringify(body),
responseKind: "turbo-stream",
})
}
ここにあるpatch
関数が、request.js
で定義されているajaxリクエストのショートハンドです。
レスポンスのデータ形式をturbo-stream
で指定できるのが嬉しいですね。
sortablejsとは
ドラッグアンドドロップで要素の順序を変更できる機能を提供するJavaScriptライブラリです。このライブラリは、要素のドラッグアンドドロップ操作に関連する様々なイベントを発火させます。
その中のonEndイベントは、要素のドラッグ操作が終了した時に発火します。
onEnd(evt)関数はこのonEndイベントのハンドラーで、evtはイベントに関連する情報を含むオブジェクトです。このオブジェクトには、ドラッグされた要素、新しいインデックス(evt.newIndex)、元のインデックス、その他のドラッグアンドドロップ操作に関連する情報が含まれています。
このイベントハンドラーは、ドラッグアンドドロップ操作が完了した後にサーバー側にデータを送信するために@rails/request.jsのpatchメソッドを使用しています。これにより、サーバー側のデータがクライアント側の変更に合わせて更新されます。
終わりに
Ajaxを使ってできることについては全てHotWireに置き換えることで、コードを書く量やわかりやすさを向上させることができると感じる良い例でした。