2012-11-24 67 views
3

我使用的是counter_cache讓MySQL的做一些簿記對我說:counter_cache不更新的模型保存後

class Container 
    has_many :items 
end 

class Item 
    belongs_to :container, :counter_cache => true 
end 

現在,如果我這樣做:在

container = Container.find(57) 
item = Item.new 
item.container = container 
item.save 

SQL日誌會有一個INSERT其次是這樣的:

UPDATE `containers` SET `items_count` = COALESCE(`items_count`, 0) + 1 
    WHERE `containers`.`id` = 57 

這是我的前把它做了。但是,container[:items_count]將陳舊!

...除非我container.reload拿起更新的值。在我的腦海裏,有些人認爲使用:counter_cache支持定製內容的一部分目的,特別是因爲在嘗試訪問items_count屬性之前,我實際上可能不需要reload。 (由於域邏輯的性質,我的模型非常密碼化,所以我有時必須在一次控制器調用中保存並創建多件事情。)

我知道我可以自己修改回調,但在我看來,這似乎是對簡單功能的一個相當基本的期望。同樣,如果我必須編寫額外的代碼才能使其完全工作,那麼實現自定義計數器可能會更容易。

我在做什麼/假設錯誤?

回答

1

雖然實際上並沒有讓容器知道該項目,但實際上,您在container.reload時執行的操作是!它。您是否嘗試過:

container = Container.find(57) 
item = container.items.create() 

這將使容器的上下文中的項目和爲您建立這些關聯。

+0

這有效。我發現它不一致,它是一種方式而不是另一種。 – sehnsucht

+0

對我來說這不起作用!只有在重載計數器更新後。我嘗試了各種樣式'create','create!','build.save!'。 – pablo

3

您不應該期望在您的容器實例中自動更新項目計數器的值。請記住,大多數Rails應用程序在多進程(通常是多服務器)配置下運行。如果一個進程在不同進程中添加與Container實例關聯的Item,則計數器的值將變爲陳舊。

+1

保持數據處於一致狀態的負擔在模型上。這就是爲什麼我們擁有不同的隔離級別的交易,並且如果擁塞足夠高以保證它的話,那麼它就是樂觀併發的原因。有人可能會在其他地方更改數據不僅適用於counter_cache,而且還是一個普遍問題 - 如果第二個表已更新,則連續兩個SELECT可能會產生不一致的數據。 在這方面,我不明白爲什麼由其他人向我的容器添加項目導致的競爭條件與我在訪問它之前更改'container.items'的任何不同。 – sehnsucht