2

私のinvite.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がnullのコードに対してクエリを実行するのはなぜですか、無駄なクエリのように見えます。

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。2番目はからInvite.where(:code => code).exists?です。

コールバックの順序はここに示されています。したがって、の代わりにコールバックassign_codeとして呼び出す必要があると思います。そして、あなたはそれがユニークであることを自分でチェックすることをスキップすることができるかもしれません。before_validationbefore_createcode

于 2013-02-11T21:38:08.233 に答える
0

RESTful APIにAccessTokenクラスを実装すると、validates_presence_ofとbefore_creationコールバックの順序で同じ問題が発生しました。
上で提案したように、_createの代わりにbefore_validationを使用しましたが、新しい問題が発生しました。更新のたびにメソッドが呼び出され、トークンキーが変更され、ユーザーのデバイスが保持するデータが古くなっていました。
それが新しいレコードであるかどうかをチェックすることによってそれを解決しました:
self.token = SecureRandom.hex if new_record?

于 2015-02-11T11:05:27.073 に答える