2010-03-08 80 views
1

如果模型在本地更改屬性,然後將其更改回來,ActiveRecord不會將更改發送到數據庫。這是偉大的表現,但如果別的東西改變數據庫,我想將它還原爲原始值,改變不採取:ActiveRecord緩存和update_attributes

model = Model.find(1) 
model.update_attribute(:a, 1) # start it off at 1 

# some code here that changes model.a to 2 
model.a = 2 # I know it changed, reflecting my local model of the change 

model.update_attribute(:a, 1) # try change it back, DOESN'T WORK 

最後一行不起作用,因爲AR認爲在數據庫仍然是1,即使其他內容將其更改爲2.如果知道新值,我如何強制進行AR更新或直接更新緩存?

注意:改變它的代碼是一個鎖定記錄的update_all查詢,但它具有混淆緩存的副作用。多臺機器讀取此表格。如果有更好的方法來做到這一點,我很想知道。

Model.update_all(["locked_by = ?", lock_name], ["id = ? AND locked_by IS NULL", id]) 

回答

4

對此使用reload方法。

model.reload(:select => "a") 

OR

你可以嘗試will_change!方法(它不清楚你的變化是如何發生的,但是你可以試試這個方法)。

model.update_attribute(:a, 1) # start it off at 1 
model.a_will_change! #fore warn the model about the change 
model.a = 2 #perform the change 
model.update_attribute(:a, 1) 
+0

這是否執行數據庫操作?我知道應該是什麼值,所以我寧願直接設置緩存。 – phillee 2010-03-08 20:47:47

+0

是的。它的確如此。這就是爲什麼我減少了所選字段的數量。 – 2010-03-08 21:08:43

+0

我已經更新了我的答案,提出了一種替代方法。 – 2010-03-08 22:02:15

0

通過哈里什謝蒂的答案是正確的,你需要調用參考重裝,但我發現了一個更好的辦法來自動做到這一點。

在要重新加載屬性,創建一個after_update回調,並呼籲重新加載,直接出現,像這樣的模型:

after_update :reload_attr 
def reload_attr 
    reload select: "attr" 
end