2014-09-04 88 views
3

我怎麼能有一個像ActiveRecord scope修改它的行爲關係?更新範圍內的關係?

具體來說,我希望能夠做到這一點:

Model.some_scope.fake_destroy_all 

哪裏fake_destroy_all是我試圖創建功能。這幾乎相當於.update_all(deleted: true)

疲軟的替代方法是:

def fake_destroy_all(relation = Model) 
    relation.update_all(deleted: true) 
end 

#... 

Model.fake_destroy_all(Model.some_scope) 

但是,這並不理想。我想要做的是這樣的:

scope :fake_destroy_all, update_all(deleted: true) 

但這並不奏效。

是否有可能做類似我所描述的事情?

+2

看看這個:http://stackoverflow.com/questions/23017070/how-to-hide-records-rather-than-delete-them-soft-delete-from-scratch/23017174#23017174 – MrYoshiji 2014-09-04 20:30:04

回答

3

試試這個:

def self.fake_destroy_all 
    self.update_all(deleted: true) 
end 

事實證明,關係保留所有的類方法。範圍也是類方法,它是允許範圍「鏈接」的確切機制。

因此,與這個模型的關係也會有這種方法,self是關係的一個實例。

範圍語法大概可以固定像這樣(現在不能測試,但要注意的λ,而不是簡單的方法調用):

scope :fake_destroy_all, -> { update_all(deleted: true) } 

我想,沒有拉姆達它有效地調用內更新此方法調用scope,對類定義。它可以與簡單的where型示波器配合使用,因爲where沒有副作用,它只返回一個適用的濾波器。它被評估一次並保存在將來使用的方法中。

但是,使用lambda時,執行一直保持到實際應用範圍,直到定義爲止。這是必要的,因爲update_all確實有副作用

如果您指定的範圍不斷變化,最簡單的情況依賴於Time.now,這種情況會隨時間而改變,並且需要每次重新評估。

但是,我建議你使用類方法:範圍更像是一個過濾器,而這更像是一個「過濾器執行」。雖然這也可能起作用,但範圍在語義上針對不同的用例。