2011-03-10 78 views
1

在我的用户模型中,我有:validates_uniqueness_of在heroku上失败?

validates_uniqueness_of:fb_uid(我使用Facebook Connect)。

但是,有时候,用户注册时会出现重复行。这真是太糟了。

两条记录的创建时间在100ms以内。我还没有能够确定它是否发生在两个单独的请求中(heroku日志记录很糟糕,只能返回到目前为止,它只发生两次)。

两件事情:

  • 有时请求需要一段时间,因为我查询FB API的名称信息,朋友和图片。
  • 我使用bigint来存储fb_uid(后端是postgres)。

我还没有能够在dev中复制。

任何想法将不胜感激。

的登入功能

def self.create_from_cookie(fb_cookie, remote_ip = nil) 
    return nil unless fb_cookie 
    return nil unless fb_hash = authenticate_cookie(fb_cookie) 
    uid = fb_hash["uid"].join.to_i 

    #Make user and set data 
    fb_user = FacebookUser.new 
    fb_user.fb_uid = uid 
    fb_user.fb_authorized = true 
    fb_user.email_confirmed = true 
    fb_user.creation_ip = remote_ip 
    fb_name_data, fb_friends_data, fb_photo_data, fb_photo_ext = fb_user.query_data(fb_hash) 
    return nil unless fb_name_data 
    fb_user.set_name(fb_name_data) 
    fb_user.set_photo(fb_photo_data, fb_photo_ext) 

    #Save user and friends to the db 
    return nil unless fb_user.save 
    fb_user.set_friends(fb_friends_data) 
    return fb_user 
end 
+0

你可以发布注册功能吗? – Spyros 2011-03-10 23:35:09

+0

已发布到问题 – Brian 2011-03-10 23:41:03

回答

1

我并不十分熟悉与Facebook连接,但有可能得到两个相同的UUID的,如果从两个单独的帐户两个独立的用户发布在非常快速连续的请求在任何请求完成之前? (否则,被称为竞态条件)validates_uniqueness_of仍可以从这种竞争条件苦,细节可以在这里找到:

http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_uniqueness_of

由于此检查是在数据库之外进行 仍有 在两个并行事务中插入重复值的机会是 。 为了保证这一点,你应该 在现场创建一个唯一的索引。 请参阅add_index以获取更多信息。

你可以真的确保这将永远不会发生通过添加数据库约束。这种添加到数据库迁移,然后运行它:

add_index :user, :fb_uid, :unique => true 

现在,用户将获得的,而不是能够完成请求,这通常是最好生成数据库中的非法数据,你必须调试错误并手动清理。

+0

哈!万分感谢。我会尽快将这个限制添加到我的fb_uid索引中。 – Brian 2011-03-10 23:46:32

0

从Ruby on Rails v3.0开始。5个模块的ActiveRecord ::验证:: ClassMethods http://s831.us/dK6mFQ

并发和完整性

使用结合该[validates_uniqueness_of] 验证方法与 ActiveRecord的::基地#保存不 保证不存在的复制 记录插入,因为唯一性 检查应用程序级别是 固有地容易出现竞争状况。 例如,假设两个用户 尝试在相同的 时间发布评论,并且评论的标题必须是 的唯一。在数据库级别,这些用户执行的 行动可能 在以下 方式交错:...

0

好像有某种代码内的竞争条件。要检查这一点,我会首先更改代码,以便首先提取Facebook值,然后才能创建一个新的Facebook对象。

然后我会强烈建议你编写一个测试来检查你的函数是否被执行一次。它似乎执行了两次。

在此基础上,等待获得Facebook结果似乎存在竞争条件。