2013-02-16 61 views
1

我試圖通過其priority:integer列管理ActiveRecord模型。我想用after_updateafter_create掛鉤管理行,以保持訂單整潔。如何最好地管理用於表示優先級的整數列

我有兩個要求:

  1. 取物品的當前的列表,並更新自己的優先級屬性遵循嚴格的順序。 示例:具有所述優先級列的三個項目的列表。

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

    成爲

    [a.priority = 1, b.priority = 2, c.priority = 3] 
    
  2. 更新所有行的優先級,以反映列表的middel增加了一個新的行。

    [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庫的一個新的列表:https://github.com/digitalcake/priority_manager

+0

我不確定你在找什麼;顯然數字1是微不足道的,而數字2似乎比較直接。你在哪裏遇到問題? – 2013-02-16 02:00:40

+0

我的問題是我真的不確定要開始。如果它不是微不足道的,你可以向我展示你所要做的事情嗎? 我得到這可能不同做一個數組的情況下工作在數據庫級別,所以什麼最適合你。 – 2013-02-16 02:11:29

+0

對於第一個,您將優先級設置爲索引+1。一旦你完成了,你知道在哪裏插入新的項目;你可以簡單地用新的項目項目創建一個新的數組,添加新的項目,然後在增加索引後添加其餘項目。 – 2013-02-16 02:14:04

回答

2

對於第一種情況,你可以不喜歡

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) } 

這就是說,如果你只在訂貨興趣,不在名單上的絕對位置會更有效的,如果不是使用整型來存儲你的優先次序,您使用彩車。通過在它們之間的對象的優先級之間分配一個值來插入一行。 IE插入一個,並用各自的優先級和/ 2

之間bÇ PBPC它分配PA =的優先級(PC + PB

這種方式整體順序保持不變,但每次插入新行時,都不需要觸摸並重新保存優先級更高的每個對象。

0

我剛剛在我正在構建的其中一個應用程序中處理完全相同的場景。 接受答案中的解決方案不起作用,因爲它將遞歸地使用回調來調用您要更新的對象(在update_attributes內部)。此外,我們需要跳過查詢內部的自我對象的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 

這裏我使用after_commit回調,這樣我就可以設置correct_priority自我,我在我的方法定義。其他回調將不起作用,因爲在提交期間值將被覆蓋。

使用update_column,以便在我不需要它們時跳過回調。

邏輯是自我解釋。