From: Brian Tickler Date: 2009-09-20T04:18:26+09:00 Subject: Re: Getting to one attribute of my marshalled array of objects Thanks Doug, I implemented all those changes. I guess I just went too far down the wrong road with trying to handle the empty inventory, so I removed that whole mechanic. Part of that was that I tried to marshal @carArray originally but messed it up somehow (it only dumped the object ID or something), and that's when I tried to marshal self instead and it worked. Not sure what I did there since when I tried again with @carArray it worked fine. I am having another issue, though. In order to delete a car, I need to number the inventory when it displays so that I can ask the user to tell me which car to delete by its number on the list (this is part of the assignment so I can't really do it another way). At first I thought I would modify the to_s on CarInventory which right now just iterates through the array of Cars using .each and calls Cars.to_s, but then I decided it would be more robust if Cars.to_s was aware of whether it was being called repeatedly as part of a listing or not, from anywhere. So I added a parameter "def to_s(listPosition=0)" to Car.to_s and changed the .each call in the CarInventory.to_s to pass a position number. When I run the progrma now though I get a really bizarre behavior...I was supposed to get this type of output with 2 cars in my data file (simplified because I am also formatting it to comform to columns, etc.): [1] VIN# Year Make Model Color Price [2] ... Instead I got the same results without any bracketed list numbers...so I added a debug counter and a puts of the relevent part of my string output, and I got this: Called 1 times [1] Called 2 times [2] Called 3 times nil VIN# [...] Called 4 times nil VIN# [...] Which is where I am stuck...after adding the parameter Ruby appears to be calling to_s 4 times now instead of 2 times and I have no idea why. The first 2 times it gets the first part of the string I am building set up correctly, but loses everything else and the second 2 times it does the whole rest of the string build correctly but ignores the first part. I have tried everything I cna thinnk of to display the strings invloved at every stage/state and it seems ok...I just can't figure out why the to_s is calling four times when it should be twice. Source below (you can run it, add a car or two, then uncomment the DEBUG lines to see what happens): ----SOURCE class Car # DEBUG: @@debugCounter = 0 def initialize(vin, year, make, model, color, price) @vin = vin @year = year @make = make @model = model @color = color @price = price end def to_s(listPosition=0) # allow for a listing position to be passed # DEBUG: @@debugCounter = @@debugCounter + 1 # DEBUG: puts "Called #@@debugCounter times" displayString = "" 80.times {displayString << " "} # lay down a canvas of spaces to build the full displayString if !self.vin displayVIN = "(No VIN)" else displayVIN = self.vin end if !self.color displayColor = "" else displayColor = "(#@color)" end # DEBUG: debugString = "[" + listPosition.to_s + "]" if listPosition != 0 # DEBUG: puts debugString displayString[0, 0] = "[" + listPosition.to_s + "]" if listPosition != 0 displayString[6, 0] = displayVIN displayString[25, 0] = @year + " " + @make + " " + @model + " " + displayColor displayString[70, 0] = @price displayString = displayString.strip # make the format look like a "normal" to_s call if passed no list position end def <=> (compare) self.year <=> compare.year end attr_accessor :vin, :year, :make, :model, :color, :price end class CarInventory @@inventoryFile = "cars.data" def initialize if File.exists?(@@inventoryFile) File.open(@@inventoryFile) do |file| @carArray = Marshal.load(file) end else @carArray = Array.new end end def save File.open(@@inventoryFile, "w+") do |file| Marshal.dump(@carArray, file) end end def addCar(car) @carArray << car end def updateCar(car) updateIndex = @carArray.index(car) if updateIndex @carArray[updateIndex] = car else puts "Cannot find car #car.vin\n" end end def delCar(car) @carArray.delete(car) end def to_s if @carArray.first @carArray.each {|car| car.to_s(@carArray.index(car) + 1)} else return "(No inventory)" end end def ==(compare) self.vin == compare.vin end def sort(sortBy) case sortBy when "V": when "M": when "P": when "Y": else end end def filter(filterArray) end attr_reader :carArray, :inventoryFile end puts "Car Inventory 1.0 - Brian Tickler\n" cars = CarInventory.new loop do puts "\n# VIN Car Description Price\n" puts "----------------------------------------------------------------------------\n" puts cars.to_s puts "----------------------------------------------------------------------------\n" puts "(A)dd a new car\n" puts "(E)dit a car\n" puts "(D)elete a car\n" puts "(S)ave changes\n" puts "(Q)uit\n" puts "\nCommand: " command = gets.chomp.upcase case when command =~ /^A/ : puts "\nAdd a new car:\n" puts "\nVIN:" vin = gets.chomp puts "\nYear:" year = gets.chomp puts "\nMake:" make = gets.chomp puts "\nModel:" model = gets.chomp puts "\nColor:" color = gets.chomp puts "\nPrice:" price = gets.chomp newCar = Car.new(vin, year, make, model, color, price) cars.addCar(newCar) when command =~ /^E/ : puts "\nEdit a car:\n" when command =~ /^D/ : puts "\nDelete a car:\n" when command =~ /^S/ : cars.save puts "\nSaved to #cars.inventoryFile\n" when command =~ /^Q/ : puts "Are you sure? [Y/N]" confirm = gets.chomp.upcase exit if confirm =~ /^Y/ next else puts "Illegal Command: #{command}" end end -- Posted via http://www.ruby-forum.com/.