2

在我的邀请.rb 模型中,我有以下内容:

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

有任何想法吗?谢谢

4

3 回答 3

3

您可能想before_validation :assign_code改用,这样代码在验证之前就设置好了。

于 2013-02-11T21:38:00.747 回答
1

第一个查询来自验证回调(在设置代码之前)并检查没有其他Invite人有空的code. 第二个是从Invite.where(:code => code).exists?

回调的顺序显示在这里。所以我认为你应该调用assign_code回调before_validation而不是before_create. 然后你也许可以自己跳过检查它code是独一无二的。

于 2013-02-11T21:38:08.233 回答
0

为我的 RESTful API 实现 AccessToken 类时,我遇到了与 validates_presence_of 和 before_creation 回调顺序相同的问题。
如上所述,我使用 before_validation 而不是 _create 但它给了我一个新问题:每次更新时都会调用我的方法,更改我的令牌密钥,然后过时用户设备保存的数据。
通过检查它是否是新记录来解决这个问题:
self.token = SecureRandom.hex if new_record?

于 2015-02-11T11:05:27.073 回答