2

メールの一意性をチェックする rspec テストを次に示します ( http://ruby.railstutorial.org/chapters/modeling-users.html#code-validates_uniqueness_of_email_testから)

require 'spec_helper'

describe User do

  before do
    @user = User.new(name: "Example User", email: "user@example.com")
  end
  .
  .
  .
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
end

著者が述べたように、私は追加しました

class User < ActiveRecord::Base
  .
  .
  .
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end

私のユーザーモデルとテストに合格します。

しかし、@user はまだデータベースに保存されていません (コードのどこにも @user.save ステートメントが見つかりません)。そのため、user_with_same_email は、データベースに同じ電子メールを持つ他のユーザーがいないため、既に一意です。次に、それはどのように機能しますか?

コンソールで同様のものを作成しました。user_with_same_email.valid? false を返します (「すでに取得されています」というエラーが表示されます) が、user_with_same_email.save は引き続き機能します。なぜ?

4

2 に答える 2

4

shoulda-matchers gemを使用できます。

# spec/models/user_spec.rb
require 'spec_helper'

describe User, 'validations' do
  it { should validate_uniqueness_of(:email) }
  it { should validate_presence_of(:email) }
  it { should validate_format_of(:email).with_message(VALID_EMAIL_REGEX) }
end

最後のものについては肯定的ではありませんが、うまくいくようです。

クリアランスを使用している場合は、ここで組み込みemail_validator機能のPRを使用できます

# app/models/user.rb
validates :email, presence: true, email: true
于 2013-05-20T19:46:06.330 に答える
2

マッチャーのソース コードは次のとおりです。be_valid

match do |actual|
  actual.valid?
end

ご覧のとおり、マッチャーは実際にはレコードを保存せずvalid?、インスタンスのメソッドを呼び出すだけです。valid?検証に合格するかどうかを確認し、合格しない場合はインスタンスにエラー メッセージを設定します。

上記の場合、最初に (成功して) 同じ電子メール ( user_with_same_email) を持つユーザーを保存しています。これは、その電子メールを持つユーザーがまだ実際に保存されていないため機能します。次に、同じ電子メールを持つ別のユーザー インスタンス ( ) で検証エラーをチェックし@userていますが、重複したレコードを実際に保存していなくても、明らかに失敗しています。

コンソールに表示される内容に関しては、save失敗してもエラーを返さない問題が考えられます。save!代わりに使用してみてください。

于 2012-10-02T01:57:12.937 に答える