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
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
···
end
never mind re-read some more and figured it out.
···
On 6/5/06, Paul D. Kraus <paul.kraus@gmail.com> wrote:
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
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
···
On Jun 5, 2006, at 10:00 PM, Paul D. Kraus wrote:
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
def increment_invoice
invoices = invoices + 1
end
def increment_ndainvoice
ndainvoice = ndainvoice + 1
end
./parse.rb:14:in `incndainvoice': undefined method `+' for nil:NilClass
(NoMethodError)
from ./parse.rb:31
from ./parse.rb:20
<snip>
#!/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 # 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 Fugal
···
On 6/5/06, Paul D. Kraus <paul.kraus@gmail.com> wrote: