2012-05-01 29 views
3

看起來validates_uniqueness_of:即使some_field屬性沒有改變(如果其他字段已經改變),some_field也會在「保存」上運行。這看起來很浪費,因爲每個validates_uniqueness_of都需要數據庫調用。我知道我可以通過一個Proc to validates_uniqueness_of來檢查some_field是否已經改變,我正在考慮通過所有的驗證並儘可能地做到這一點。我想知道的是:爲什麼Rails驗證未改變的屬性?

1)人們對錶演感興趣嗎?

2)爲什麼它不是validates_uniqueness_of的默認行爲來檢查屬性是否先改變?

3)有沒有很好的理由對沒有改變的屬性進行驗證?

我正在使用Rails 2.3(目前 - 我們正在進行升級)。我不知道這是Rails 3中的相同情況。

+0

關於2和3,值可以放到Rails應用程序之外的數據庫中。因此,另一個應用添加的值可能會使您的不變屬性無效。此外,您的驗證可能會隨着時間的推移而變化,導致無變化的屬性無效。 – niiru

+0

@niiru:感謝您花時間回覆。從用戶的角度來看,編輯記錄的一部分真的很奇怪,然後被告知該記錄的另一部分是無效的,這是沒有編輯的,並且在邏輯上與變化無關。另外,在你的場景中,如果rails應用程序在字段上執行唯一性,那麼其他應用程序是否也應該這樣做? –

+0

肯定!但是,您可能正在處理與多個應用程序綁定的數據庫,並不是所有這些數據庫都對數據驗證負責,因爲您的應用程序是...... – niiru

回答

2

如果某人直接更改了數據庫中的值,該怎麼辦?

如果某些其他(非rails應用)應用也訪問數據庫會怎麼樣?

在上述所有場景中,您仍然希望數據有效,以便您的rails應用程序按預期運行。如果數據被篡改(通過其他應用程序或直接在數據庫中),您的rails應用程序會拋出一個錯誤,因爲它不會期望這些數據。

話雖如此,這是默認行爲。默認行爲通常更具限制性,以保持數據的有效性並最大限度地減少錯誤,遺漏和偶爾出現的錯誤。如果你擔心你的情況下的性能,也許你的對象被更新得非常頻繁,並且你沒有經常更新的字段有一個冗長的自定義驗證,並且你不想每次運行驗證時間,那麼定製默認行爲就像你在問題中描述的那樣完美。

0

我剛剛遇到了與Rails 3.0應用程序相同的問題。我通過檢查用戶是否編輯了唯一屬性來解決此問題。以下是我的User對象的相關代碼摘錄。

class User < ActiveRecord::Base 

attr_accessible :email, :password, :ha1, :ha1b, :sip_username, :domain 

validates :sip_username, :presence => true, :uniqueness => true, 
         :unless => :update_username?, 
         :exclusion => {:in => %w(9196), 
         :message => "9196 is reserved, please choose another"} 
def update_username? 
    # check to see if we are updating a sip_username for an existing user 
    stored_user = User.find_by_sip_username self.sip_username 
    # the id of the user is the same as me and sip_username hasn't been changed. skip validations. 
    if (stored_user.present?) 
    stored_user.id == self.id && stored_user.sip_username == self.sip_username 
    end 
end 
相關問題