2013-02-11 50 views
1

在我invite.rb模型我有以下幾點:爲什麼validates_uniqueness_of在before_create之前運行?

class Invite < ActiveRecord::Base 
    before_create :assign_code 
    validates_uniqueness_of :code, :case_sensitive => false, :message => "This invite code is taken!" 

    protected 

    # Create a safe random token and ensuring it's uniqueness for the model 
    def assign_code 
    begin 
     code = SecureRandom.urlsafe_base64 
    end while Invite.where(:code => code).exists? 
    self.code = code 
    end 

問題是我看到下面的跟蹤日誌。爲什麼rails對空值的代碼進行查詢,看起來像是浪費的查詢。

Invite Exists (0.5ms) SELECT 1 AS one FROM "invites" WHERE "invites"."code" IS NULL LIMIT 1 
Invite Exists (0.3ms) SELECT 1 AS one FROM "invites" WHERE "invites"."code" = 'mTGCX0yCyTgplGfGQ5hGeA' LIMIT 1 

任何想法?謝謝

回答

2

你可能想用before_validation :assign_code代替,這樣代碼在驗證之前就被設置了。

1

第一個查詢來自驗證回調(在代碼設置之前),並檢查沒有其他Invite有空code。第二個是從Invite.where(:code => code).exists?

回調的順序顯示爲here。所以我認爲你應該呼叫assign_code作爲before_validation回調,而不是before_create。然後你可以跳過檢查你自己,code是獨一無二的。

0

爲我的RESTful API實現AccessToken類,我得到了與validates_presence_of和before_creation回調命令相同的問題。
如上所示,我使用before_validation而不是_create,但它給了我一個新問題:我的方法在每次更新時都會調用,更改我的令牌密鑰,然後過時用戶設備保存的數據。
通過檢查是否是新記錄來解決:
self.token = SecureRandom.hex if new_record?

相關問題