Ruby on rails 如何最好地管理用于表示优先级的整数列

Ruby on rails 如何最好地管理用于表示优先级的整数列,ruby-on-rails,ruby,rails-activerecord,Ruby On Rails,Ruby,Rails Activerecord,我试图通过ActiveRecord的priority:integer列来管理ActiveRecord模型。我想用after\u update和after\u create钩子管理行,以保持它们的顺序整洁 我有两个需要: 获取项目的当前列表并更新其优先级属性以遵循严格的顺序。 示例:具有所述优先级列的三项列表 [a.priority = 4, b.priority = 66, c.priority = 92] 变成 [a.priority = 1, b.priority = 2, c.prior

我试图通过ActiveRecord的
priority:integer
列来管理ActiveRecord模型。我想用
after\u update
after\u create
钩子管理行,以保持它们的顺序整洁

我有两个需要:

  • 获取项目的当前列表并更新其优先级属性以遵循严格的顺序。 示例:具有所述优先级列的三项列表

    [a.priority = 4, b.priority = 66, c.priority = 92]
    
    变成

    [a.priority = 1, b.priority = 2, c.priority = 3]
    
  • 更新所有行的优先级,以反映在列表中间添加的新行

    [a.priority = 1, b.priority = 2, c.priority = 3, d.priority = 4]
    
    添加
    e.priority=2
    创建一个新的

    [a.priority = 1, e.priority = 2, b.priority = 3, c.priority = 4, d.priority = 5]
    

  • github回购:

    对于第一种情况,您可以执行以下操作

    Model.order("priority ASC").each_with_index {|m,i| 
      m.update_attribute(:priority, i+1) }
    
    第二个呢

    Model.where("priority >= ?", new_priority).each {|m| 
      m.update_attribute(:priority, m + 1) }
    
    这就是说,如果您只对排序感兴趣,而不是对列表中的绝对位置感兴趣,那么如果您不使用整数来存储优先级,而是使用浮点数,则效率会更高。通过在要插入行的对象的优先级之间指定一个it值来插入行。IE在b和c之间插入a,其优先级分别为pb和pc,并为其分配pa=(pc+pb)/2的优先级


    这样,整体顺序保持不变,但您不需要每次插入新行时都以更高的优先级触摸并重新保存每个对象。

    我只是在我正在构建的一个应用程序中处理了完全相同的场景。 接受答案中的解决方案不起作用,因为它将递归地使用回调调用您尝试更新的对象(在update_属性中)。我们还需要跳过查询中self对象的id

    以下是我最终的做法,它似乎适用于所有情况

    after_commit :order_priorities, :if => :persisted?
    after_destroy :handle_priorities_when_destroyed
    
    def order_priorities
        correct_priority = MyModel.where('id != ? AND priority < ?',id,priority).count + 1
        MyModel.where.not(id:id).order(:priority).each_with_index {|x,i|
            if x.priority < priority
                x.update_column(:priority, i+1) 
            else
                x.update_column(:priority, i+2)
            end
        }
        self.update_column(:priority,correct_priority) 
    end
    
    def handle_priorities_when_destroyed
        MyModel.where.not(id:id).order(:priority).each_with_index {|x,i|
                x.update_column(:priority, i+1)
        }
    end
    
    在提交后:排序优先级,:if=>:持久化?
    销毁后:在销毁时处理优先级
    def order_优先级
    更正\u priority=MyModel.where('id!=?和priority<?',id,priority)。计数+1
    MyModel.where.not(id:id).order(:priority)|
    如果x.priority
    在这里,我使用after_commit回调,以便能够为我在方法中定义的self设置正确的_优先级。其他回调将不起作用,因为该值将在提交期间被覆盖

    使用update_列,以便在我不需要回调时跳过回调


    逻辑是不言自明的。

    我不确定你在找什么;显然,数字1是微不足道的,而数字2似乎相对简单。你哪里有问题?我的问题是我不确定我们该怎么开始。如果不是太琐碎的话,你能告诉我你会怎么做吗?我认为在数组环境下做这件事可能与在db级别上做这件事有所不同,所以什么对你来说最合适。对于第一件事,你将优先级设置为索引+1。一旦你这样做了,你知道在哪里插入新的项目;您只需创建一个包含新项目前的项目的新数组,追加新项目,然后在增加其索引后追加其余项目。
    a
    b
    c
    。。。表示单独的行(即模型实例),对吗?您希望能够在列表中的特定位置插入
    e
    ,并更新其他
    priority
    值,对吗?mu太短,您的回答是正确的