0

假設我在Dummy模型上有registration_id屬性。 它的數據類型是字符串。 它的長度可以是10-14個字符之間的任何東西,但是我想僅在最後10個字符處提供唯一性驗證。 (奇怪,但真)驗證ActiveRecord中字符串部分的唯一性

現在我該如何實現這一目標?

我所想的:

  1. Dummy表創建另一個屬性last_ten_chars_registration_id舉行最後的10個字符,並把唯一該屬性。 (由於計算屬性顯然不適用於唯一性驗證)

  2. 我可以創建自定義驗證器並編寫查詢。 我不知道(可能爲like查詢)

任何人都可以給我建議任何更好的方法來實現這一目標?

+0

http://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations –

+0

我喜歡'last_ten_chars_registration_id'的想法。您可以對列進行索引,以獲得這些唯一性查詢的良好性能。數據庫性能並不完全是我的舵手,但我會想象隨着時間的推移和增長,「像」查詢不會如此高效。 – GoGoCarl

+0

不完全不同意,但通過優化標準化。除非有優化的理由,例如數百萬條記錄或緩慢的查詢,否則我仍然相信LIKE檢查更好。如果你有兩列有相同的數據,那麼你有多確定它永遠不會失去同步,保持它們匹配需要額外的邏輯。自定義驗證強制執行業務邏輯,即不能使用具有相同最後10個字符的註冊ID的兩條記錄。 – SacWebDeveloper

回答

0

您可以使用像這樣的自定義驗證程序。

class Dummy < ActiveRecord::Base 
    validates_with RegistrationValidator, :fields => [:registration_id] 

    # Whatever else... 
end 

class RegistrationValidator < ActiveModel::Validator 
    def validate(record) 
    reg_id = record.registration_id.last(10).join 
    if Dummy.where('registration_id LIKE ?',"%#{reg_id}") 
     record.errors[:registration_id] << "Registration ID taken!" 
    end 
    end 
end 
+0

修復了record.registration_id中的拼寫錯誤。 – SacWebDeveloper

0

和GoGoCarl一樣,我也認爲它在很大程度上取決於您需要的性能。自定義查詢(不是LIKE,而是RIGHT(registration_id, 10)函數,至少在MySQL中)我認爲沒有問題,除非Dummy表很大或者您需要查詢速度超快。在這種情況下,我也會用最後的10個字符做特殊列,並附帶一個db索引。

一個實用的解決方案可能是首先進入自定義查詢路由,因爲它對我來說似乎更簡單,如果性能開始受影響,則切換到特殊列。

你也可以做你自己的基準,例如如果你的表現沒有問題,你可以填寫一個測試Dummy表格,其中包含您期望的記錄數量並自行查看。

另請參閱此related SO question字符串SQL函數的性能,其中解決方案是類似的。