3

私はHartlのRailsチュートリアルを終了しましたが、混乱の1つの領域がまだ支配しています。いつ使用する@variableのか、いつ使用する必要があるのか:variable​​、そしていつvariable正しいのか。

これが私がチュートリアルから取ったいくつかのサンプルコードです:

describe "micropost associations" do
    before { @user.save }
    let!(:older_micropost) do 
      FactoryGirl.create(:micropost, user: @user, created_at: 1.day.ago)
    end
    let!(:newer_micropost) do
      FactoryGirl.create(:micropost, user: @user, created_at: 1.hour.ago)
    end
    .
    .
    .
    it "should destroy associated microposts" do
      microposts = @user.microposts.dup
      @user.destroy
      microposts.should_not be_empty
      microposts.each do |micropost|
        Micropost.find_by_id(micropost.id).should be_nil
      end
    end
  end
  .
  .
  .
end

と比較して:

describe Micropost do
  let(:user) { FactoryGirl.create(:user) }
  before { @micropost = user.microposts.build(content: "Lorem ipsum") }

これ(および他のコード)が私に提起するいくつかのより具体的な質問があります:

  1. @userそれは件名であるため、最初のスニペットにが必要@ですか?
  2. 常に新しい変数を使用して宣言し:ますか?(実際にはそうではないと確信していますが、その理由と理由はわかりません。)
  3. 後で使用して作成した変数を参照するときに、もう一度:使用:しますか?たとえば、print(:older_micropost)またはを実行する場合print(older_micropost)、違いはありますか?(let2番目のスニペットのステートメントを参照してください)。
  4. beforeそれらはすべて、ブロック内でも外部と同じように機能しますか?一部のコードはbeforeブロックの内側/外側でのみ機能することがわかりました(例older_micropost.destroy)。

私はこれに対する答えを他の場所で探しましたが、、、の3つすべての議論を見つけることができませ@:

編集:これがコードの3番目のスニペットです。今回は私自身のものです。何が機能し、何が機能しないかについてコメントしました。

describe "deleting a user following" do
  let(:userid) { @user.id }
  before { print(@user.id.inspect) # this works
           @user.destroy }         # this works
  @user.destroy                    # this doesn't
  print(@user.id.inspect)          # this doesn't
  subject { other_user }
  its(:followed_users) { should_not include(userid) }
end

(明らかに、コメント付きコードの4行すべてを一緒に実行するのではなく、beforeブロックの内側に2つ、または外側に2つ実行します)

これらのステートメントがbeforeブロック内でのみ機能するのはなぜですか?

4

2 に答える 2

3

彼は古い RSpec 構文と新しい RSpec 構文を混ぜ合わせているため、やや混乱しています。

RSpec の元の化身は、全体を通してインスタンス変数を使用していました。そう:

before { @user = User.new }

it "should be valid" do
  @user.should be_valid
end

RSpec は後に、以下を使用して変数に値を代入する機能を獲得しましたlet

let(:user) { User.new }

it "should be valid" do
  user.should be_valid
end

letシンボルを引数として取り、メソッドが参照されたときに指定された結果を生成するメソッドを定義します。の主な利点letは、遅延評価されることです。これにより、変数の設定を延期できます。これは、例を入れ子にする場合に特に効果的です。

Hartl のように 2 つのパラダイムを組み合わせて使用​​することはできますが、混乱を招く可能性があります。いずれかのスタイルを使用することをお勧めします。

@user は、最初のスニペットに @ が必要ですか?それは件名ですか?

@ を使用するか使用せずに ( を使用して) 定義しlet、常に同じ方法で参照する必要があります。@useruser同じではありません。

常に : を使用して新しい変数を宣言しますか? (実際にはそうではないことはかなり確信していますが、その理由と理由はわかりません。)

: はシンボルのプレフィックスです。内でのみ使用しますlet

: を使用して作成した変数を後で参照する場合、再び : を使用する必要がありますか? たとえば、print(:older_micropost) または print(older_micropost) を実行した場合、違いはありますか? (2 番目のスニペットの let ステートメントを参照してください)。

変数を参照するときは、シンボルではなくメソッド名を使用します。そうmicropostではありません:micropost

それらはすべて、before ブロック内と外側のブロック内で同じように機能しますか? 一部のコードは before ブロックの内側/外側でのみ機能することがわかりました (例: old_micropost.destroy)。

サンプル本文で機能するコードはすべて、before ブロックでも機能する必要があります。うまくいかないのは、例の外にコードを配置することです。

let(:user) { User.new(:name => "Phil") }

before { puts user.name } # "Phil"

it "sets the name" do
  puts user.name # "Phil"
end

puts user.name # undefined local variable or method `user' 
于 2013-02-15T04:27:07.567 に答える
1

これはインスタンス変数です。つまり、コントローラーからビューに、またはその逆に情報を渡す必要がある場合は常に、これを使用します。@variable

現在:は記号に使用されています。つまり、ほとんどの場合文字列に似ていますが、文字列全体を一度に比較するため、メモリの点で単純な文字列よりも安価です。

これに関する詳細については、記事http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/をお読みください。

于 2013-02-14T05:46:07.583 に答える