これはMHartlのRuby on Railsチュートリアルからのコードです。インスタンス変数(@user)が必要な理由と、ローカル変数。また、インスタンス変数はクラスのインスタンス内の変数であると想定されているため、@ userはどのクラスからインスタンス化されますか?
require 'spec_helper'
describe User do
before { @user = User.new(name: "Example User", email: "[email protected]") }
subject { @user }
it { should respond_to(:name) }
it { should respond_to(:email) }
end
そのインスタンスでローカル変数を使用すると、そのスコープがbefore
に制限されるため、エラーが発生します。 @user
はUser型ですが、describe
ブロックのインスタンス変数です。 Rspecには、実行時に各describe
ブロックからクラスを作成する魔法があります。各例(it
ブロック)は、最終的にそのクラスのサブクラスになります。クラス継承により、例で@user
。
2017年5月14日編集
リンクされたブログ投稿は利用できなくなりました。 WaybackMachineリンクで更新+関連するセクションをここにインライン化します。
この ブログ投稿 で詳しく説明されているように、これはアンチパターンと見なされることに注意してください。代わりにlet
を使用してください。
let
には次の利点があります。
ローカル変数はローカルメソッドのスコープ内にのみ存在するため、ローカル変数を使用することはできません。 before
、subject
、およびit
は、同じクラス内で異なるスコープを生成します。
次のコード
_before { user = User.new(name: "Example User", email: "[email protected]") }
_
で呼び出すと、未定義の変数が発生します
_subject { user }
_
インスタンス_@user
_は、クラスUser
のインスタンスです(結局のところ、_User.new
_で作成します)。
ただし、インスタンス変数の代わりに、let
コマンドを使用することをお勧めします。また、あなたが定義する場合
_subject { User.new(name: "Example User", email: "[email protected]") }
_
before
の使用は必要ありません。また、let(:subject)
を定義するのと同じように、インスタンスにアクセスするためにsubject
メソッドを使用できるという追加の利点も得られます。
subject
ad it
ブロックは異なるスコープの下にあるため、ローカル変数は機能しません。 @user
は、内部でRSpecによって生成されたクラスに属しています。