acts_as_listとjQueryで並べ替えを実装する
jQueryのsortableを用いて並べ替えを実装する Rails
acts_as_list
モデルの並び順を簡単に操作できるようにするGem
昔のRails1系あたりでは標準で搭載されていたらしいが、 途中でGemとして切り離されて現在は独立したGemとして存在する。
引用:acts_as_list: gem か plugin か
本家がこちら。 https://github.com/swanandp/acts_as_list
導入の仕方などはドキュメントにわかりやすく書かれているのでそこを参考すると良さそう。 acts_as_listでは positionカラム がデータのソート基準となるよう決まっている。 なのでacts_as_listを使いたい場合は、対象とするテーブルのカラムにposition絡むを追加しましょう。
# has_manyでtodo_itemsを持つ親モデル class TodoList < ActiveRecord::Base has_many :todo_items, -> { order(position: :asc) } end # belongs_toでtodo_listに紐づく子モデル class TodoItem < ActiveRecord::Base belongs_to :todo_list # scopeで定義する acts_as_list scope: :todo_list end todo_list = TodoList.find(...) # move_to_bottomで値を操作1,2,3とあるならば1が3になり2,3が繰り上がる todo_list.todo_items.first.move_to_bottom # move_higherで1,2,3,とあるならば2,1,3と変更される todo_list.todo_items.last.move_higher
また、最近の紹介記事ですと、Qiitaに上がっているjnchitoさんの記事が素晴らしくわかりやすかったです。 実装の際に参考にさせてもらいました。 Rails 4で作るドラッグアンドドロップで表示順を変更できるサンプルアプリ(スクリーンキャスト付き)
動画は見ていませんが初心者にもわかりやすいように筆者が参考にした記事や、 動画を用いての実装方法まで紹介していてさすがですね。
今回自分は ranked_model を使った実装を行っていないので機会があればそちらも使ってみたいなと思います。 どうやらranked-modleの方がパフォーマンスが良いようです。(検証はしてません)
Railsで順番を管理するgemとして、ranked-model gemを使います。 acts_as_listも有名ですが、ranked-modelの方がパフォーマンス的に優れています。
ドラッグ&ドロップで並べ替えを行う実装
jQueryのsortableを用いて、ドラッグ&ドロップで操作を行う実装を紹介します。 上記でacts_as_listを紹介しましたが、今回の実装では用いません。 acts_as_listではなくjQueryのsortableを用いることでも並べ替えを良い感じにできるんだぜってことを紹介したいと思います。
# Railsで良い感じに実装するためのGem達 gem 'jquery-ui-rails' gem 'jquery-turbolinks'
// application.jsで読み込みます //= require jquery-ui/effect-highlight //= require jquery-ui/sortable
D&Dを行った際の処理 $('.table-sortable').sortable でsortableを適用させる。 D&Dをトリガーにしてajax処理を行いDB側のposition値を変更する使用
// table_sort.js $(function() { return $('.table-sortable').sortable({ axis: 'y', items: '.sentence', update: function() { // ajax処理で並べ替え後の値をサーバー側に渡す $.ajax({ type: 'POST', url: '/sort', dataType: 'json', // $('.table-sortable').sortable('serialize') で変更後の値を取得 data: $('.table-sortable').sortable('serialize') }); }, // ここはおまけで変更完了エフェクトを付け足す stop: function(e, ui) { return ui.item.children('td').effect('highlight'); } }); });
controller側の実装
def sort Content.all.each do |sentence| content.position = params[:content].index(content.position.to_s) + 1 content.save end render nothing: true end
model側での実装 値を追加した際にpositionカラムに値の最大値をセットするために before_createにset_positionメソッドを定義します
before_create :set_position def set_position if max =Content.where(hoge_id: hoge_id).maximum(:position) self.position = max + 1 end end
slimの実装 id="position_#{content.position}"でデフォルト値をセット
table.table.table-striped.table-sortable thead tr th id th name th description tbody - @contents.each do |content| tr.sontent id="position_#{content.position}" td= content.id td= content.name td= content.description
簡単にイケてる実装ができて便利!
参考
Rails 4で作るドラッグアンドドロップで表示順を変更できるサンプルアプリ(スクリーンキャスト付き)