如何实现todos / list的保存顺序?

时间:2017-07-02 19:40:22

标签: ruby-on-rails postgresql todomvc

我正在开发一个与todo list非常相似的应用程序,除了todos的顺序很重要,可以由用户更改。

在db中保存此订单的好方法是什么,而不必在更改订单时重新保存整个待办事项列表?

我正在开发Rails,Postgres和React,最新版本。

我想将它保存为User Todos中的数组(可能有多个应用程序用户),但我认为它可能会使事情变得复杂,因为每次创建待办事项时我都要保存List还

2 个答案:

答案 0 :(得分:1)

您可以查看acts_as_list gem,为此您必须在表格中添加其他列位置。但这将对记录进行大规模更新。但这个宝石经常更新。

如果您想要一个优化的解决方案并尽量减少更改列表时的更新次数,那么您应该检查ranked_model gem,但这个不经常更新。有一个简要的说明: -

  

这个库是从头开始使用ARel编写的。这使代码比许多实现更清晰。排名模型也被优化为尽可能少地写入数据库:排名存储为-2147483648和2147483647之间的数字(MySQL中的INT范围)。当一个项目被赋予一个新的位置时,它会在两个邻居之间分配一个等级号。这允许在两个邻居之间没有数字之前可以进行多次项目移动。当发生这种情况时,排名模型将尝试将其他记录移开。如果项目不再容易转移,它将重新平衡排名组中所有成员的排名分布。

你可以参考这个gem并制作你自己的实现,因为它只支持rails 3& 4。

答案 1 :(得分:0)

这有点令人头疼,但这是我的想法:

create table orderedtable (
   pk SERIAL PRIMARY KEY,
   ord INTEGER NOT NULL,
   UNIQUE(ord) DEFERRABLE INITIALLY DEFERRED
)

DEFERRABLE INITIALLY DEFERRED 很重要,因此中间状态不会在重新排序期间导致违反约束。

INSERT INTO orderedtable (ord) VALUES (1),(2),(3),(4),(5),(10),(11)

请注意,在此表中插入时,在 ord 值之间留出间隙会更有效,以便在稍后插入或移动行时将需要移动的订单值的数量降至最低。连续值用于演示目的。

诀窍如下:您可以使用递归查询找到从特定值开始的连续值序列。

例如,假设您想在位置 3 上方插入或移动一行。一种方法是将当前位于位置 4 和 5 的行向上移动一个以打开位置 4。

WITH RECURSIVE consecutives(ord) AS (
  SELECT ord FROM orderedtable WHERE ord = 3+1 --start position
UNION ALL
  SELECT orderedtable.ord FROM orderedtable JOIN consecutives ON orderedtable.ord=consecutives.ord+1 --recursively select rows one above, until there is a hole in the sequence
)
UPDATE orderedtable
SET ord=orderedtable.ord+1
FROM consecutives
WHERE orderedtable.ord=consecutives.ord;

以上将 ord1,2,3,4,5,10,11 重新编号为 1,2,3,5,6,10,11,留下一个洞为 4。 如果在 ord=4 处已经有一个洞,上面的查询就不会做任何事情。

然后通过赋予它现在免费的 ord 值 4 来插入或移动另一行。

您可以通过将 +1s 更改为 -1s 将行向下而不是向上推。