# Object Troubles - undefined method \`+'

**URL:** <https://www.ruby-forum.com/t/object-troubles-undefined-method/62528>\
**Category:** Ruby\
**Created:** [June 5, 2006, 10:01pm UTC](https://www.ruby-forum.com/t/object-troubles-undefined-method/62528 "2006-06-05T22:01:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul\_DSKraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed655f/32.png) [@Paul\_DSKraus](https://www.ruby-forum.com/u/Paul_DSKraus)\
**Post date:** [June 5, 2006, 10:01pm UTC](https://www.ruby-forum.com/t/object-troubles-undefined-method/62528/1 "2006-06-05T22:01:32Z")

</div>

I am parsing a text file that is 3 fields per line deliminted by pipes  
‘|’  
Each line contains a customer code, shipmethod, and customer name.  
Each line represents an invoice that was cut.

I need to count all invoices and then count all invoices that went out  
next  
day air saver.  
From working with the pick axe it seems to me that you have a class with  
two  
attributes invoice, and nda invoice.  
You then store your objects in a hash for easy lookup.

When i run the below program I get this error…  
./parse.rb:14:in `incndainvoice': undefined method`+’ for nil:NilClass  
(NoMethodError)  
from ./parse.rb:31  
from ./parse.rb:20

TIA,  
Paul

Here is my class and program …

#!/usr/bin/env ruby

class Customer  
attr\_reader :invoices, :ndainvoices  
attr\_writer :invoices, :ndainvoices  
def initialize  
@invoices = 1  
@ndainvoices = 0  
end  
def increment\_invoice  
invoices = invoices + 1  
end  
def increment\_ndainvoice  
ndainvoice = ndainvoice + 1  
end  
end

customers = Hash.new

# open(‘NdaInvoiceCount.txt’,‘r’).each\_line do |line| (customer\_code, ship\_method, customer\_name) = line.chomp.split(’|’) if customers[customer\_code] customers[customer\_code].increment\_invoice else customers[customer\_code] = Customer.new end customers[customer\_code].increment\_ndainvoice if ship\_method

‘SAVGRD’  
end

here is some sample data…  
0000016324|SAVGRD|Dupage Prosthetics  
0000038955|SAVGRD|TRUDELL ORTH & PROS SERVICES  
0000019155|UPS |Scott Orthotic Labs  
0000061674|UPS |COMPREHENSIVE BRACE & LIMB CTR LLC  
0000008593|U02G |Huron Valley Assoc  
0000039954|SAVGRD|Island Coast Orthopedics  
0000028719|UPS |Paul Richelson’s Feet First  
0000003455|FEDGND|CLARK ORTH  
0000019297|UPS |J. Slawner LTD.  
0000061508|UPS |LEVY & RAPPEL

---

<div class="post-metadata">

**Author:** ![Paul\_DSKraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed655f/32.png) [@Paul\_DSKraus](https://www.ruby-forum.com/u/Paul_DSKraus)\
**Post date:** [June 5, 2006, 10:13pm UTC](https://www.ruby-forum.com/t/object-troubles-undefined-method/62528/2 "2006-06-05T22:13:57Z")

</div>

> class Customer  
> attr\_reader :invoices, :ndainvoices  
> attr\_writer :invoices, :ndainvoices  
> def initialize  
> @invoices = 1  
> @ndainvoices = 0

Here you initialize 2 _instance_ variables, @invoices and @ndainvoices

end

> def increment\_invoice  
> invoices = invoices + 1

The _local_ variable ‘invoices’ does exist yet, so ‘nil + 1’ raises the  
error.  
You probably intended:

@invoices = @invoices + 1

end

> def increment\_ndainvoice  
> ndainvoice = ndainvoice + 1

same here

end

---

<div class="post-metadata">

**Author:** ![Paul\_DSKraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed655f/32.png) [@Paul\_DSKraus](https://www.ruby-forum.com/u/Paul_DSKraus)\
**Post date:** [June 5, 2006, 10:18pm UTC](https://www.ruby-forum.com/t/object-troubles-undefined-method/62528/3 "2006-06-05T22:18:09Z")

</div>

On Jun 5, 2006, at 10:00 PM, Paul D. Kraus wrote:

> def increment\_ndainvoice  
> ndainvoice = ndainvoice + 1  
> end

You are trying to set local variables. Instance variables are  
prefixed with @. If you were trying to call your attr\_writer method,  
you need to prefix it with self:

self.invoices += 1

Here is a more idiomatic way of writing what you would like:

class Customer  
attr\_accessor :invoices, :ndainvoices  
def initialize  
@invoices = 0  
@ndainvoices = 0  
end  
end

customers = Hash.new { |h, k| h[k] = Customer.new }  
IO.foreach(‘NdaInvoiceCount.txt’) do |line|  
(customer\_code, ship\_method, customer\_name) = line.chomp.split(’|’)  
customers[customer\_code].invoices += 1  
customers[customer\_code].ndainvoices += 1 if ship\_method ==  
‘SAVGRD’  
end

– Daniel

---

<div class="post-metadata">

**Author:** ![Paul\_DSKraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed655f/32.png) [@Paul\_DSKraus](https://www.ruby-forum.com/u/Paul_DSKraus)\
**Post date:** [June 5, 2006, 10:14pm UTC](https://www.ruby-forum.com/t/object-troubles-undefined-method/62528/4 "2006-06-05T22:14:35Z")

</div>

never mind re-read some more and figured it out.

---

<div class="post-metadata">

**Author:** ![Paul\_DSKraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed655f/32.png) [@Paul\_DSKraus](https://www.ruby-forum.com/u/Paul_DSKraus)\
**Post date:** [June 5, 2006, 10:21pm UTC](https://www.ruby-forum.com/t/object-troubles-undefined-method/62528/5 "2006-06-05T22:21:24Z")

</div>

On 6/5/06, Paul D. Kraus [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ./parse.rb:14:in `incndainvoice': undefined method `+’ for nil:NilClass  
> (NoMethodError)  
> from ./parse.rb:31  
> from ./parse.rb:20

> ```
> invoices = invoices + 1
> end
> def increment_ndainvoice
> ndainvoice = ndainvoice + 1 # this is line 14
> end
> 
> ```
> 
> end

You’re problem here is that on line 14, you are actually using a local  
variable. This is a little tricky, since it’s actually your assignment  
that is changing the context of the right hand side. What happens is  
that the parser sees “ndainvoice =” and assumes you’re creating a new  
local variable called “ndainvoice”; this new local variable then masks  
the “ndainvoice” method. Since it’s value is nil (the default value of  
an unassigned-to variable), the effect of the line is:

ndainvoice = nil + 1 # ndainvoice is a local variable here

In order to get ruby to recognize the assignment as a method call,  
rather than an assignment to a new local variable, you need to prefix  
“self.”:

self.ndainvoice = ndainvoice + 1

The reference to ndainvoice on the right hand side is correctly  
interpreted as a method call since there is no local variable of the  
same name to mask it. Alternatively, you can use the instance variable  
directly by prefixing an “@” (as you do in initialize):

@ndainvoice = @ndainvoice + 1

As a final step, you can also use += to shorten the “a = a + b” pattern:

self.ndainvoice += 1

# or

@ndainvoice += 1

Incidentally, you have the same problem on line 11.

Jacob F.
