Skip to content

Instantly share code, notes, and snippets.

@jwo
Created October 29, 2012 16:41
Show Gist options
  • Save jwo/3974731 to your computer and use it in GitHub Desktop.
Save jwo/3974731 to your computer and use it in GitHub Desktop.
No Instance Variables in Specs (for @Blighte)

(this started on twitter)

The microposts spec starts out with

let(:user) { FactoryGirl.create(:user) }
  before do
    # This code is wrong!
    @micropost = Micropost.new(content: "Lorem ipsum", user_id: user.id)
  end

  subject { @micropost }

Michael is telling you the code is wrong to set an instance variable in the spec. Instead, you should just:

  let(:user) { FactoryGirl.create(:user) }
  subject { Micropost.new(content: "Lorem ipsum", user_id: user.id) }

This way, the subject is set to the Micropost.new

The same happens in my Dog example... We are setting the subject to a new instance of Dog.

describe Dog do

This will set the subject to Dog.new

class Dog
def initialize(name="sparky")
@name = name
end
def name
@name
end
end
require 'rspec'
require './dog'
describe Dog do
it { should respond_to(:name) }
end
@blithe
Copy link

blithe commented Oct 29, 2012

I understand that you are saying that I shouldn't use instance variables in the spec files. I'm still new so I don't have all of the best practices (like variable scope) down yet so I appreciate you pointing that out. Can you explain (or give a link for) why it is bad to use an instance variable in a spec file?

I'm not so sure @mhartl is saying the instance variable is the "wrong" part in that line of code though. In section 10.1.2 he says that the problem is that the user_id attribute is accessible. As far as I can tell, he repeatedly uses instance variables in his spec files in the tutorial (for the micropost model and the user model).

@jwo
Copy link
Author

jwo commented Oct 29, 2012

I definitely shouldn't have put words in Michael's mouth; I assumed what was "wrong" with the spec syntax without knowing.

IMHO, using instance variables is not as flexible as using lets.

  • with nested contexts, you can easily override lets in subsequence child contexts
  • a let is a call to a method, and can easily be moved to a true method if you need one
  • purely aesthetic preferences

@mhartl
Copy link

mhartl commented Oct 30, 2012

That's not why the code is wrong. Using instance variables in specs is fine, although I prefer to use let when I can. The code is wrong because setting the user_id doesn't work as soon as you define attr_accessible. Instead, you need to define the micropost through the association, using code like user.microposts.build(...), as described in Section 10.1.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment