When you are inside a class, you are not always forced to use the self receiver explicitly when calling a method residing in the same class (or higher in the hieararchy). However, there is a time when you HAVE to use self or else it just won’t do what you want : This time is when you call an attribute writer.
not_an_assignment # <== self is implicit
assign_fiesta = "Hello!" # <== self is not implicit! assign_fiesta is a local variable
self.assign_fiesta = "Hello!" # <== Now we're talking!
Why is this so? Well, it makes some sense when you think about it. If your attribute writers (methods trailing with an = sign) would’nt require to be called with an explicit receiver, how could you tell ruby when you want to assign to a local variable instead of calling a method? Sure, ruby could check if the thing to the left corresponded to the name of a method in the current class and, based on the answer, call a method or assign to a local variable. But what if the method did not reside in the current class but in the parent class… or in the parent class of the parent class (and so on)? It would become a great source of confusion, don’t you think?
Say for example you had a method in your class that was setting the local variable color (color=”blue”). This method could work without any problem for months… until you decide to add a new attribute writer with the name color= in the parent class. From now on (that is, if ruby would be using some detection technique like the one mentionned earlier), your initial method would not deal with the local variable color anymore, it would call the color= method in the parent class! This could get really messy and error prone.
So, instead of trying to guess if the thing to the left is a method with a trailing = sign or a local variable, ruby assumes that it is always a local variable and that the whole expression is a standard assignment. That being said, you could use self only to call attribute writers and omit it for other methods… but personally I don’t like that kind of inconsistency.
I like to remind myself that a method never floats in the air and that it is always contained into an object. That’s why most of the time I prefer to specify the receiver before the name of a method… no wonder if I’m outside or inside the object.