Why ruby attr_accessor doesn't work in this case? [duplicate]

I would like to understand why this wouldn't work. I know the notion of attr_accessor.

class MyClass
  attr_accessor :num

  def initialize(num = 0)
    @num = num
  end

  def calulate
    while num < 100
      num = num + 1
    end

    puts num
  end

end

c = MyClass.new
c.calulate

This gives me error.

my_class.rb:11:in `calulate': undefined method `+' for nil:NilClass (NoMethodError)

however, If I change num to @num . it works. Would any one can explain this?

Update

Also if I run this line of code, it will return all same id.

puts num.object_id
puts @num.object_id
puts self.num.object_id

result

1
1
1

Solution 1:

The problem comes from the line num = num + 1

Accessing works, but for assigning to an accessor from inside a class you would need to do

self.num = num + 1

What you are doing the first time you run num = num + 1 is to create a new variable num and shadowing the method.

So in the while loop every access to num would refer to your new variable, making an explicit assignment to self.num= makes ruby know that you are not creating a new variable.