From: Douglas Seifert Date: 2009-09-20T21:06:48+09:00 Subject: Re: Getting to one attribute of my marshalled array of objects --000e0cd358d2f3f6ec04740132db Content-Type: text/plain; charset=ISO-8859-1 Brian, 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. > I would not go down this road. A car should not care if it is being displayed as part of a listing of other cars or if it is alone. It should just know how to display itself. In addition, adding a parameter to to_s is bad ruby style: to_s has well-defined semantics in the ruby language. I suggest before you go any further, you pick up a copy of "Programming Ruby". If you can't afford the money, the first edition is available for free on line: http://www.rubycentral.com/book/. The book does a far better job than I ever could of explaining how the to_s method works in the Ruby world. > > 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.): > > After looking at your implementations, I see what you are trying to accomplish. A better idea in my opinion would be to leave the counting logic to the CarInventory class. It is the class that knows about a list of cars. I noticed also that you tried to put some logic in to line up the car attributes in a nice column layout. You are reinventing the wheel here, unfortunately. One thing you should look up right away is is the % method of class String: $ ri String#% --------------------------------------------------------------- String#% str % arg => new_str ------------------------------------------------------------------------ Format---Uses _str_ as a format specification, and returns the result of applying it to _arg_. If the format specification contains more than one substitution, then _arg_ must be an +Array+ containing the values to be substituted. See +Kernel::sprintf+ for details of the format string. "%05d" % 123 #=> "00123" "%-5s: %08x" % [ "ID", self.id ] #=> "ID : 200e14d6" You should do an ri Kernel#sprintf to see all the good stuff that can go in the format string. If you are familiar with c/c++ at all, this will be familiar to you. I'm not sure also in your original to_s method on the CarInventory class how it ever worked. The each method of class Array returns the Array itself. Your to_s method would end up returning an array of Car objects and it might have been pure accident that it looked ok in your command loop. Here is a revised to_s for the CarInventory class. It handles the indexing problem and makes sure it returns a String object in all cases. I would implement Car#to_s without a parameter and use the formatting methods above to get a nice column layout def to_s if @carArray.first counter = 0 @carArray.map {|car| counter += 1; "[%3d] %s" % ]counter, car.to_s]}.join("\n") else return "(No inventory)" end end I am not sure how a beginner goes about accumulating the knowlege necessary to make implementing this method easy. There is a lot of knowledge bundled up in this implementation of to_s: use of Array#map and Array#join. Knowledge of String#% and by implication, Kernel#sprintf. I have done a lot of reading I guess. This whole thread is reminding me of a recent blog post by Jamis Buck, a guy who I think it is fair to say is a Ruby community luminary: http://weblog.jamisbuck.org/2009/9/17/there-is-no-magic-there-is-only-awesome-part-1 If you ever want to get good with Ruby, you need to apply his four rules: 1. *Know thy tools.* 2. *Know thy languages.* 3. *Know thy libraries.* 4. *Know thy communities.* Applying these rules, you would know about the % method of the String class and about Kernel#sprintf and Array#map and Array#join. So keep studying! It is a high hill to climb, but once you get over the top, your programs will reach the level of conciseness that Ruby is famous for. -Doug Seifert --000e0cd358d2f3f6ec04740132db--