First, read this answer, which is the most-upvoted Ruby post in StackOverflow history. It will help you understand attr_accessor
and its cousins attr_reader
and attr_writer
.
Besides that, your code has many problems.
First, you should not name an Array with a singular variable name like item
. Use a plural items
to make its purpose clear.
Second, the name item2
is not good. For your attribute, use something descriptive like counter
, and for the variable passed as an argument to initialize it, let's use something descriptive like initial_count
.
Third, your increment
method takes an optional argument but then ignores it. Wouldn't it be surprising if someone called box.increment(2)
and the attribute was incremented by only 1? The intent of this method is to use counter += n
instead of counter += 1
.
Fourth, to set counter
from within the class, we need to use self
. So instead of counter += n
, we have to do self.counter += n
.
Finally, consider whether you want the attributes to be readable and writable from an outside source, or whether you want to reserve write privileges to the object itself. Because you have methods to add things to items
and to increment counter
, you probably want to conceal write privileges. I would use attr_reader
publicly and attr_writer
privately.
Incorporating these suggestions, here's the resulting code:
class Box
attr_reader :counter, :items
def initialize(initial_count)
@counter = initial_count
@items = []
end
def add(product)
items << product
end
def empty?
items.empty?
end
def increment(n = 1)
self.counter += n
end
private
attr_writer :counter, :items
end
Now you can do this, all of which makes sense, more or less:
>> cart = Box.new(123)
>> cart.increment(2)
>> cart.counter
#> 125
>> cart.add('A product')
>> cart.add('Another product')
>> cart.items
#> ["A product", "Another product"]
But if you try to set counter
or items
directly, you'll get an error:
>> cart.counter = 1
#> NoMethodError: private method `counter=' called for #<Box:0x007fc13e17dc50>