2011-02-03 167 views
38

我該如何做到這一點?如何在不觸摸updated_at屬性的情況下更新單個屬性?

試圖建立2種方法,稱爲

def disable_timestamps 
    ActiveRecord::Base.record_timestamps = false 
end 

def enable_timestamps 
    ActiveRecord::Base.record_timestamps = true 
end 

和更新方法本身:

def increment_pagehit 
    update_attribute(:pagehit, pagehit+1) 
end 

和關閉使用回調,比如開時間戳:

before_update :disable_timestamps, :only => :increment_pagehit 
after_update :enable_timestamps, :only => :increment_pagehit 

,但它不是更新任何東西,甚至是所需的屬性(pagehit)。

有什麼建議嗎?我不想爲了統計頁面數量而創建另一個表格。

+0

嘗試使用`update_attributes!(:pagehit => pagehit + 1)`並查看是否有任何錯誤。順便說一句,你是否在這裏粘貼了`def disable_timestamps`兩次,或者你的代碼是否一樣? – Zabba 2011-02-03 15:02:01

+0

[有沒有辦法避免自動更新Rails時間戳字段?](http://stackoverflow.com/questions/861448/is-there-a-way-to-avoid-automatically-updating-rails-timestamp場地) – 2016-05-12 18:46:30

回答

12

如果所有你想要做的是增加一個計數器,我會用increment_counter方法來代替:

ModelName.increment_counter :pagehit, id 
85

作爲update_attribute的替代方案,在Rails 3.1+中,您可以使用update_column

update_attribute跳過驗證,但會觸碰updated_at並執行回調。

update_column跳過驗證,不碰updated_at,並且不執行回調。

因此,如果您不想影響updated_at並且不需要回調,那麼update_column是一個不錯的選擇。

查看http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html瞭解更多信息。

另請注意,update_column將更新內存模型中的屬性值,並且不會將其標記爲髒。例如:

p = Person.new(:name => "Nathan") 
p.save 
p.update_column(:name, "Andrew") 
p.name == "Andrew" # True 
p.name_changed? # False 
2

爲了避免Monkeypatchingtroubles你也可以使用ModelName.update_all用於此目的:

def increment_pagehit 
    self.class.update_all({ pagehit: pagehit+1 }, { id: id }) 
end 

這還沒有觸及記錄的時間戳。

2

這不是一個好主意,這樣做:

self.class.update_all({ pagehit: pagehit+1 }, { id: id }) 

應該

self.class.update_all("pagehit = pagehit + 1", { id: id }) 

的原因是,如果兩個請求是平行的,在第一個版本都將更新的網頁點擊量因爲它使用保存在Ruby內存中的數字。第二個選項使用sql服務器將數字增加1,以防兩個查詢同時發生,服務器會一個接一個地處理它們,最終會得到正確數量的頁面訪問。

-1

如果精度是不是真的那麼重要,你不要指望代碼運行很多次,你可以嘗試改變保存在數據庫中updated_at值,就像這樣:

u = User.first 
u.name = "Alex 2" # make some changes... 
u.updated_at = u.updated_at + 0.000001.second # alter updated_at 
u.save 

,這樣的Rails實際上會嘗試保存相同的值,而不是用Time.now替換它。

1

你也有decrementincrement(和他們的爆炸版本)不會改變updated_at,不要去觸發驗證回調,並顯然很方便的計數器/整數。

相關問題