Rails中的Netflix-esque列表排序

时间:2010-12-16 03:30:10

标签: ruby-on-rails activerecord ruby-on-rails-3

我想允许用户以与我可以对Netflix队列进行排序相同的方式指定项目序列。例如,给出一个观点:

 #  |  Item Name
----+------------
 1  |  one
 2  |  three
 3  |  four
 4  |  two

如果用户将商品名称“2”的订单更改为“2”并保存,则他们应该看到:

 #  |  Item Name
----+------------
 1  |  one
 2  |  two
 3  |  three
 4  |  four

我尝试过使用before_save:

class List < ActiveRecord::Base
  has_many :items

  before_save :sequence_items

  def sequence_items
    items.sort{|f,s|f.number <=> s.number}.each_with_index do |item, index|
      item.update_attributes(:number => index + 1)
    end
  end
end

但结果是:

 #  |  Item Name
----+------------
 1  |  one
 2  |  three
 3  |  two
 4  |  four

3 个答案:

答案 0 :(得分:3)

我发现我可以使用acts_as_list plugin。我将number表中的Item属性重命名为position,然后修改了以下代码:

class Item < ActiveRecord::Base
  belongs_to :list

  acts_as_list
end

class List < ActiveRecord::Base
  has_many :items

  before_save :sequence_items

  def sequence_items
    items.each_with_index do |item, index|
      item.insert_at(item.position || index + 1)
    end
  end
end

现在无论何时保存列表,每个项目都将插入到提供的位置。我有许多没有位置值的现有项目因此我添加了|| index + 1以确保它们在列表末尾被分配了一个位置。

答案 1 :(得分:0)

this您要找的是什么?

答案 2 :(得分:0)

不太了解Rails(或Ruby,或编程),但我查看了Ruby的Array文档,insert()和delete_at()方法给了我一个想法。

在items表中有一个序列列(从0开始),然后创建一个item对象数组(甚至只是后端的item_id)。

            0 1 2
    array = A B C
 user wants B A C

array.insert(0, array.delete_at(1))

            0 1 2
    array = B A C

如果他们可以一次做出很多改变,那么这显然会在每次插入后改变指数。这意味着您应该只通过item_id删除。

array.insert(0, array.delete(item.id))

delete方法返回已删除内容的值。通过使序列与实用程序数组的位置同义,它使逻辑更容易。

完成所有更改后,您只需将新数组位置映射到项目的序列值。