When do I use the at sign (@), colon (:) and just the variable name in rspec / rails?

I finished the Hartl Rails tutorial, and another area of ​​confusion is when I use @variable

, when should I use :variable

, and when is it variable

correct?

Here is some sample code I took from the tutorial :

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

      

Compared with:

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

      

Here are some more specific questions that this (and other code) is asking me:

  • Is it required @user

    @

    in the first snippet because it's a topic or ..?
  • Do I always declare new variables using :

    ? (Actually I'm sure this is not the case, but I don't understand where they are or why.)
  • When I refer later to the variable created with :

    , use again :

    ? For example, if I need to execute print(:older_micropost)

    or print(older_micropost)

    , is there any difference? (See instructions let

    in the second snippet).
  • Do they all work the same in a block before

    as outside of one? I found that some code will only work inside / outside the block before

    (for example older_micropost.destroy

    ).

I've searched elsewhere for an answer to this question, but I can't find a discussion of all three @

, :

and nothing.

Edit: Here's a third piece of code, this time my own. I commented what works and what doesn't:

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

      

(Obviously I am not running all 4 lines of code with comments together, I am running two inside a before block or two outside)

Why do these operators only work inside a block?

+3


source to share


2 answers


It mixes old and new RSpec syntax, which makes it somewhat confusing.

The original incarnation of RSpec used instance variables. So:

before { @user = User.new }

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

      

RSpec later gained the ability to assign values ​​to variables with let

:

let(:user) { User.new }

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

      

let

takes a character as an argument and defines a method that produces the specified result when the method is called. The main advantage let

is that it is priced lazily. This allows you to defer setting a variable, which works especially well with nesting examples.

You can mix and match the two paradigms like Hartle does, but this can be confusing. It is best to use one style or the other.

Do you need @user @ in the first snippet because it's a topic or ..?



It must be defined with @ or without (using let

) and then always quoted the same way. @user

and user

- they are not the same thing.

I always declare new variables using :? (Actually I'm pretty sure this is not the case, but I don't understand the whys and wherefores there.)

Symbol: - a prefix for a symbol. You would only use it in let

.

When I refer later to the variable I created using:, do I use: again? For example, if I was doing print (: old_micropost) or print (old_micropost), is there any difference? (See the let statement in the second snippet).

When referring to a variable, you use the method name, not the symbol. So micropost

, not :micropost

.

Do they all work the same within the pre-block as outside the one? I am that some code will only work inside / outside the a before the block (like old_micropost.destroy).

Any code that works in the body of the example should also work in the block before the block. What won't work is placing the code outside of the example, like this:

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' 

      

+2


source


This is an instance variable, means that whenever you need to pass information from controller to views or vice versa, we usually use this @variable

Now :

used for characters, means they are like strings most of the time, but they are cheaper than simple strings in memory since it compares the entire string at once.



Read more about this in the article http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/

+1


source







All Articles