Sai Dandamudi
Sai Dandamudi

Reputation: 83

ruby: Trouble understanding classes and defining variables with @

I am currently doing an rspec tutorial and am having difficulties with reading the tests. The current test I am trying to read is:

 describe Book do

  before do
    @book = Book.new
  end

  describe 'title' do
    it 'should capitalize the first letter' do
      @book.title = "inferno"
      @book.title.should == "Inferno"
    end

I can understand what it is asking me to do: create a class Book and a method inside that class to capitalize. However my thoughts on how to code this is completely wrong (I have seen an example of code that works in this case)

What I tried to do:

class Book
    def initialize(book)
        @book = book
    end

    def title(@book)
        @book.capitalize
    end
end

Solution that ended up working:

class Book

    attr_reader :title

    def initialize(title=nil)
      @title = title && title.capitalize!
    end

    def title=(new_title)
        @title = new_title && new_title.capitalize!
    end
end

I do not understand exactly what the @ does. I thought it was to create a variable that works throughout the entire class. In addition, I am wondering why @title is used instead of @book (which is specified in the rspec test).

In addition, I am struggling with the "before do" part of the code and why it asks for @book = Book.new

Also the part with the && is confusing as well. Why is it not ok to just put @title = title.capitalize!

I would be happy to clarify any of this if it does not make sense (I know this post is long).

Upvotes: 1

Views: 196

Answers (1)

lurker
lurker

Reputation: 58244

The @ is a fundamental construct in Ruby: an instance variable for a class. So you don't have to pass it as a param within methods of the class. It's known by the entire instance of the class. See, for example, Instance Variables and Accessors for details.

So the following isn't really valid since you don't pass instance variables as method parameters:

def title(@book)
    @book.capitalize
end

The && will only go to the second statement if the first is true or not nil. For example

def initialize(title=nil)
  @title = title && title.capitalize!
end

Will set the class' instance variable @title to the parameter title.capitalize! as long as title isn't nil. If title is nil, then @title will be set to title (i.e., nil). So if the class is created without a parameter, then @title will be set to nil and an error won't be generated from calling nil with the method capitalize!.

Upvotes: 2

Related Questions