… the funny part is also the error message, which states that NoMethodError: undefined method '-' for nil:NilClass, which seems to indicate that it is the second x, which is read as nil, instead of the err being with the assigning part.
I think you’re right. I just got caught in this simple trap writing some code yesterday. If you have a large class with many attr_reader, attr_writer and attr_accessor, it might get overwhelming to check all the instance variables before creating local variables.
Accessor are here for outside access. Use self.x in this case (self access your object from outside, so you get access only to public methods). Without accessor, use @x to access your Instance Variable. It’s the normal way in Ruby. You define a @variable, you use @variable in your code.
In your case (x -= 1), internally, Ruby first get the x object (here x don’t exist, so it’s initialized to nil), and attempt to call on x the method “-” with your parameter (here 1). The fact that Ruby decompose this simple line in two actions can be checked here :
In irb, type :
x # You get undefined local variable or method x
x += 1 # You get the undefined method + for nil class
x # You get nil. Ruby in it's first action has created your x variable to nil
Great, no ?
This is why you get this strange error about a missing method : Numeric objects have the “-” method (and lot of other, but it’s not our problem here). Nill object have not. So you get a method error. Really, it’s normal.
In irb, try to do :
Prefer use @x in your code and let the use of your accessors for outside access only.
Always use self when you want use setter following assignment signature, in short : Any method name ending with “=”… And especially if you use object with dynamic method generation like ActiveRecord does (at least, one method ending with “=” for each field).