web-dev-qa-db-ja.com

オブジェクトを保存した後に「リロード」メソッドを使用するのはなぜですか? (Hartl Rails Tut 6.30)

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.emailmixed_case_email保存済みの内容に設定されると、@user.reload.email@user.emailは同じものになりませんか?私はそれを試すためだけにリロードメソッドを取り出しましたが、テストで何も変わらないようでした。

ここで何が欠けていますか?

28
sixty4bit

はい、この場合は@user.reload.email@user.emailは同じものです。しかし、@user.reload.emailの代わりに@user.emailを使用して、データベースに正確に保存されているものを確認することをお勧めします。テストには影響しません。

編集:また、チェックしているのはデータベースに保存されているものなので、@user.reload.emailはデータベースに保存されたものを正確に反映し、@user.email

32
Hardik

インメモリとデータベース

インメモリとデータベースとの違いを理解することが重要です。任意の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

22
Derrick Mar
reload 

オブジェクト(ここでは@user)の属性をデータベースからリロードします。オブジェクトに、現在データベースに保存されている最新データが常にあることを常に確認します。

これにより、回避することもできます

ActiveRecord::StaleObjectError

これは通常、オブジェクトの古いバージョンを変更しようとしたときに発生します。

7

同じものでなければなりません。全体のポイントは、reloadメソッドがデータベースからオブジェクトをリロードすることです。これで、新しく作成したテストオブジェクトが正しい/期待される属性で実際に保存されているかどうかを確認できます。

5

この例で確認したいのは、before_save内のapp/models/user.rbコールバックが機能するかどうかです。 before_saveコールバックは、すべてのユーザーの電子メールをデータベースに保存する前にダウンケースに設定する必要があります。したがって、第6章演習1では、メソッドreloadを使用して、効果的にダウンケースとして保存されます。

1
Asarluhi