Hartl's Rails 4チュートリアルの第6章の演習に取り組んでいます。最初の演習では、ユーザーのメールアドレスが正しく入力されていることを確認します。
require 'spec_helper'
describe User do
.
.
.
describe "email address with mixed case" do
let(:mixed_case_email) { "[email protected]" }
it "should be saved as all lower-case" do
@user.email = mixed_case_email
@user.save
expect(@user.reload.email).to eq mixed_case_email.downcase
end
end
.
.
.
end
ここで「再読み込み」メソッドが必要な理由はわかりません。 @user.email
がmixed_case_email
と保存済みの内容に設定されると、@user.reload.email
と@user.email
は同じものになりませんか?私はそれを試すためだけにリロードメソッドを取り出しましたが、テストで何も変わらないようでした。
ここで何が欠けていますか?
はい、この場合は@user.reload.email
と@user.email
は同じものです。しかし、@user.reload.email
の代わりに@user.email
を使用して、データベースに正確に保存されているものを確認することをお勧めします。テストには影響しません。
編集:また、チェックしているのはデータベースに保存されているものなので、@user.reload.email
はデータベースに保存されたものを正確に反映し、@user.email
インメモリとデータベースとの違いを理解することが重要です。任意のRubyコードはインメモリです。たとえば、クエリが実行されるたびに、データベースの対応するデータを使用して新しいインメモリオブジェクトが作成されます。
# @student is a in-memory object representing the first row in the Students table.
@student = Student.first
説明用のコメント付きの例を次に示します
it "should be saved as all lower-case" do
# @user is an in-memory Ruby object. You set it's email to "[email protected]"
@user.email = mixed_case_email
# You persist that objects attributes to the database.
# The database stores the email as downcase probably due to a database constraint or active record callback.
@user.save
# While the database has the downcased email, your in-memory object has not been refreshed with the corresponding values in the database.
# In other words, the in-memory object @user still has the email "[email protected]".
# use reload to refresh @user with the values from the database.
expect(@user.reload.email).to eq mixed_case_email.downcase
end
より詳細な説明を見るには、これを参照してください post 。
reload
オブジェクト(ここでは@user)の属性をデータベースからリロードします。オブジェクトに、現在データベースに保存されている最新データが常にあることを常に確認します。
これにより、回避することもできます
ActiveRecord::StaleObjectError
これは通常、オブジェクトの古いバージョンを変更しようとしたときに発生します。
同じものでなければなりません。全体のポイントは、reloadメソッドがデータベースからオブジェクトをリロードすることです。これで、新しく作成したテストオブジェクトが正しい/期待される属性で実際に保存されているかどうかを確認できます。
この例で確認したいのは、before_save
内のapp/models/user.rb
コールバックが機能するかどうかです。 before_save
コールバックは、すべてのユーザーの電子メールをデータベースに保存する前にダウンケースに設定する必要があります。したがって、第6章演習1では、メソッドreload
を使用して、効果的にダウンケースとして保存されます。