2013-02-11 98 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?

相关问题