Простая сортировка списков в rails
Допустим, в качестве примера, у нас есть некоторый список который мы хотим сортировать с минимальными действиями со стороны пользователя.
Стоит заметить, что этом примере я использую модель Page со следующими полями:id(int), name(string), pos(int)
Итак, после генерации список должен выглядеть так:
<ul id=”sortlist”>
<li id=”item_1>Первый, пошел</li>
<li id=”item_2>Второй, пошел</li>
<li id=”item_3>Третий, пошел</li>
<li id=”item_4>Четвертый, пошел</li>
<li id=”item_5>Пятый, пошел</li>
</ul>
Еще один момент заключается в id тега li, как можно заметить он состоит и двух частей это item и какое то число. Число - это id из выше упомянутой таблицы. Зачем это нужно будет понятно ниже.
Следующий этап, сделать возможным перетаскивание пунктов внутри списка. Славься RJS, делается это одной строкой, а именно так:
<%= sortable_element “sortlist”, :url => { :action => ‘update_sorted_list’ } %>
sortable_element, во-первых - позволит двигать список с id = “sortlist”, во-вторых - при перемещении любого из элементов списка(бросании) отправит запрос XMLHttpRequest методу update_sorted_list. В этом случае это будет массив значений id тега li(точнее того что идет после знака _ ) в том порядке в каком они будут отсортированы. Пример для наглядности: предположим мы решили, что пятый пойдет вторым и переместили его туда, тогда запрос будет таким [1,5,2,3,4]
Доступ в контроллере мы можем получить через params[:sortlist]. Как же нам сохранить результат? Все просто, так как нам передаются id записей в таблице, нам всего лишь нужно сопоставить их с индексами в передаваемом массиве и эти индексы внести в таблицу в колонку pos. Как это выглядит в коде контроллера:
def update_sorted_list
params[:sortlist].each_with_index do |id, p|
Page.update(id, :pos => p)
end
render :nothing => true
end
Все, теперь все должно работать. Куда интереснее организация деревьев, но об этом потом как-нибудь.
P.S.
Чтобы список после перезагрузки выводился в правильном порядке он должен быть отсортирован по колонке pos это будет выглядеть как-то так
def index
@items=Page.find(:all, :order => “pos”)
…..
end