jqueryのマウスでグリグリするやつをRails+Ajaxで更新しるのをやってみたいなぁと思い
ちょっと試してみました。
参考サイトの内容が超絶役に立ちました。ありがとうございます。
参考
・Sortable List in Ruby on Rails 3 – Unobtrusive jQuery | Web Tempest
・JQuery UI Sortable を使ってドラックアンドドッロプでRuby on Railsの一覧表示の順を設定する - @yuumi3のお仕事日記
・Sortable - jQuery UI API 1.8.4 日本語リファレンス - StackTrace
・Collapsible Drag & Drop Panels Using jQuery
How to
JQuery / JQuery UIを使えるようにします。
(20120107修正:application.html.erbからapplication.jsで読み込むように修正)
#application.js //= require jquery //= require jquery-ui
htmlの構造
こんなviewを作ります。
グリグリの単位は2行目のdiv.dragboxです。
div.column div.dragbox id="group_<%= group.id %> h2 dl dt dd
ポイントはグリグリ対象の要素にidを「_」付きで作成します。(id以外の要素でも可能です。参考URL参照)
この例だと、ajax.POST時のデータとして下記のような形式で簡単に操作できます。
group[]=1&group[]=2&group[]=3
Rails側ではpost[:group]で取得できますね。
CSRF用token
POSTなのでCSRFのWARNING(WARNING: Can't verify CSRF token authenticity)が出ないように
view側でtokenを作っています。POST時に合わせて送ります。
(httpのheadに仕込む方法もあるようです。)
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
js
ポイントは3つ。
・sortableによるグリグリ実装
・sortable('serialize') 前述のデータ形式
・authenticity_token
$(function(){ $('.column').sortable({ connectWith: '.column', handle: 'h2', cursor: 'move', placeholder: 'placeholder', forcePlaceholderSize: true, opacity: 0.4, update: function() { $.ajax({ url: '/groups/sort', type: 'POST', dataType: 'text', data: $(this).sortable('serialize') + '&authenticity_token=' + $('#authenticity_token').val(), }) } }) .disableSelection(); });
Rails contorller
def sort params[:group].each_with_index{|row, i| Group.update(row, {:ordinal => i + 1})} render :nothing => true end
scss抜粋
/* ------------------------------ Drag and Drop ------------------------------ */ .column{ width:280px; margin-right:.5%; min-height:300px; background:#fff; float:left; .dragbox{ margin:5px 2px 20px 0; background:#fff; position:relative; border:1px solid #ddd; -moz-border-radius:5px; -webkit-border-radius:5px; h2{ margin-bottom:5px; padding:5px; background:#f0f0f0; border-bottom:1px solid #eee; cursor:move; } } .placeholder{ background: #f0f0f0; border:1px dashed #ddd; } }