20

これは、M Hartl の Ruby on Rails チュートリアルからのコードの一部です。インスタンス変数 (@user) が必要な理由と、ローカル変数を使用しない理由を誰でも説明できますか? また、インスタンス変数はクラスのインスタンス内の変数であると想定されているため、@user はどのクラスからインスタンス化されているのでしょうか?

require 'spec_helper'

describe User do

  before { @user = User.new(name: "Example User", email: "user@example.com") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }
end
4

3 に答える 3

32

そのインスタンスでローカル変数を使用すると、そのスコープが に制限されるためbefore、エラーが発生します。はUser タイプですが、ブロック@userのインスタンス変数です。describeRspec には、実行時に各describeブロックからクラスを作成する魔法があります。各例 (itブロック) は、そのクラスのサブクラスになります。クラスの継承により、例を見ることができます@user

2017-05-14 編集

リンクされたブログ投稿は利用できなくなりました。Wayback Machine リンクで更新 + 関連するセクションをここにインライン化します。

このブログ投稿で詳しく説明されているように、これはアンチパターンと見なされることに注意してください。let代わりに使用してください。

let次の利点があります。

  • 1 つの例で複数回使用するとメモ化されますが、複数の例ではメモ化されません。
  • 遅延ロードされるため、変数を参照しない例で変数を初期化するのに時間を無駄にすることはありません。
  • 変数名にタイプミスがあると、例外が発生します。
于 2012-09-28T18:18:47.453 に答える
12

ローカル変数はローカル メソッドのスコープ内にのみ存在するため、ローカル変数を使用することはできません。before、同じクラス内で異なるスコープsubjectを生成します。it

次のコード

before { user = User.new(name: "Example User", email: "user@example.com") }

で呼び出すと、未定義の変数が発生します

subject { user }

インスタンス@userはクラスのインスタンスですUser(結局のところ、 で作成しますUser.new)。

ただし、インスタンス変数の代わりに、コマンドを使用したい場合がありますlet。また、定義すると

subject { User.new(name: "Example User", email: "user@example.com") }

の使用は必須でbeforeはありません。subjectまた、インスタンスにアクセスするために使用できるメソッド ( define と同等) を取得するという追加の利点も得られますlet(:subject)

于 2012-09-28T18:19:38.017 に答える
2

subject広告itブロックは異なるスコープにあるため、ローカル変数は機能しません。@user内部で RSpec によって生成されたクラスに属します。

于 2012-09-28T18:19:19.943 に答える