From: Brian Tickler Date: 2009-09-19T03:00:37+09:00 Subject: Getting to one attribute of my marshalled array of objects I have looked around for an answer to this on the mailing list and Google searches, but I am not finding anything, so sorry if this question seems too basic but... I am just learning Ruby, and one of my class assignments is writing a command line app that tracks an inventory of cars, each car having 6 attributes: VIN, year, make, model, color, and price. We are supposed to use 2 objects for this exercise, a Car class and a "List of Cars" class. Then a menu that allows adding a car to the list, deleting a car from the list, and showing the list. I could probably done this assignment as-is :)...but I wanted to go a little bit further. It did not seem to make sense that this app did not call for any persistence and once you made your inventory of cars and then left the app they were gone. So, armed with pickaxe, I tried to add file handling, but...that didn't make sense either: since I was using Car objects and a CarInventory object that is just an array of Car objects, converting the objects all the time into a format where I could put them into a delimited text file and then read them out again seemed crazy. Then I read farther in pickaxe (past what my class goes into, unfortunately), and I found Marshalling. That seemed like exactly what I wanted...I could just dump the CarInventory object with it's whole array of Cars (into a file called cars.data in this case) and then read it right back in when needed. It is almost working, too :). But, I am having a problem figuring out how to connect all the dots from A to D. A couple of things are nagging: - The first time the app is run, there is no cars.data file, so I have to handle that, which I am doing now but it's far from elegant...the app will decide you don't have any car inventory, initialize the inventory with a Car that has all nil attributes, and ask you to enter the first car, then you can Save. This has some issues in that even though I tried to write the code to later overwrite the "nil car", it is still there somehow :). - More importantly, once I have a Saved cars.data file and I use Marshal.load on it, I don't want that "enter the first car" routine to kick in, so I try to check the first Car object in CarInventory and see if its VIN number is nil or not. Somehow I am missing the boat here, and I am sure it's something simple. When I try to get from Marshalled object -> CarInventory instance -> first Car object -> first Car.vin I get the following: cars.rb:106: undefined method `[]' for # (NoMethodError) I am including the entire app below, it's not too big though I am sure it is much bigger and clunkier than it needs to be ;)...like I said I am jsut learning Ruby...any help would be appreciated in fixing my immediate and dire issues, and/or anything about making the whole app work more smoothly. You can ignore some of the other also-not-actually-required-for-this-assignment bells and whistles I have partially implemented for now. Sorry, I realize it's a bit messy. ----SOURCE class Car def initialize(vin, year, make, model, color, price) @vin = vin @year = year @make = make @model = model @color = color @price = price end def to_s if !self.vin @displayVIN = "(No VIN)" else @displayVIN = self.vin end if !self.color @displayColor = "" else @displayColor = "(#@color)" end "#@displayVIN\t#@year #@make #@model #@displayColor\t#@price\n" end def <=> (compareThisCar) self.year <=> compareThisCar.year end attr_reader :vin, :year, :make, :model, :color, :price attr_writer :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 @carArray[0] = Car.new(nil, nil, nil, nil, nil, nil) end end def save File.open(@@inventoryFile, "w+") do |file| Marshal.dump(self, file) end end def addCar(car) if car.vin == nil @carArray[0] = car else @carArray << car end end def updateCar(car) updateIndex = @carArray.find {|vinMatch| car.vin == vinMatch} if updateIndex @carArray[updateIndex] = car end end def delCar(car) @carArray = @carArray - car end def to_s @carArray.each {|car| car.to_s if car.vin} end def sort(sortBy) case sortBy when "V": when "M": when "P": when "Y": else end end def filter(filterArray) end end puts "Car Inventory 1.0\n" cars = CarInventory.new firstCar = cars.carArray firstCar = firstCar[0] if !firstCar.vin puts "\nNo car inventory found, please enter the first car:" 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) else cars.sort("V") cars.filter(nil) end loop do puts "\nVIN#\t\tCar:\t\t\tPrice:\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 "(L)ist cars by VIN\n" puts " by (M)ake and Model\n" puts " by (P)rice\n" puts " by (Y)ear\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 =~ /^L/ : puts "\nList car inventory by VIN:\n" when command =~ /^M/ : puts "\nList car inventory by Make and Model:\n" when command =~ /^P/ : puts "\nList car inventory by Price range:\n" when command =~ /^Y/ : puts "\nList car inventory by Year\n" when command =~ /^S/ : cars.save 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/.