Hello Everybody, First of all, thank you so much for participating to this list and help poor Ruby newbies like me! I feel the need to start this email with an apology. I am a terrible programmer. Ruby is the only thing that could possibly convince me to start programming again. I hadn't fallen in love with a computer language in a _long_ time! I can say that I "know" Ruby. I have a very good memory, which helped me along the way. I don't know it well, and I lack the necessary experience to be comfortable with it, but I "know" it. However, I am absolutely hopeless at *designing* anything in terms of objects and OOP. This is why I have the feeling I am just about to embarrass myself. But hey... I started writing my first "real" program in Ruby, and here I am, thinking: is this correct? Would a "real" programmer do this like way? So, here I am. I have a file system, with the following contents: [...]/A/ [...]/B/ [...]/C/ [...]/D Under /A/, there is: /A/abcexample / iinet.net.au/ In each directory, there are the following files: name surname password state unconfirmed_flag moderator_flag <-- The file can exist (flag = true ) or not exist (flag = false) I know there are much better ways of doing so, and that this approach creates a lot of tiny files, but unfortunately, at least for now, I am stuck with it. If you are curious, this is how the subscribers' information is stored for Free Software Magazine (http://www.freesoftwaremagazine.com). I wrote (see: I didn't write "designed"! :-) ) a class to access this information on the file system. Here it is: --------------------------------------------------- #!/usr/local/bin/ruby -w class Subscribers # Get the config file's contents # begin @@config_data_dir=IO.read("#{ENV['HOME']}/.subs/ data_dir") @@config_data_dir.chomp! rescue SystemCallError STDERR.puts("WARNING! Can't find the config file!"); @@config_data_dir="" end def initialize() @good_state=false # This might be completely useless @first_letter="" @full_path="" @attr_values={} end # This is the same as initialize... for now! # (who knows...) # def de_initialize @good_state=false @first_letter="" @full_path="" @attr_values={} end # This just checks that the directory actually # exists. It creates a "link" # def link_to_fs(email) # Gets the person's information # @good_state=true @first_letter=email[0,1].upcase @full_path=@@config_data_dir+"/current/"+ @first_letter+"/"+email+"/" @attr_values={} @attr_values[:email]=email # Hang on: if the file doesn't exist, undo everything # if ! File.exist?(@full_path) de_initialize() return false end true end def get_flag(flag) File.exist?(@full_path+flag.to_s) end def get_field(field) # Email is special: it's not in a file # if( field == :email) return @attr_values[:email] end # Either return the existing @attr_values[field], or # (if it's nil) reads it from the file system. # CACHE! # begin @attr_values[field]||=IO::read(@full_path +field.to_s) rescue SystemCallError nil end end def set_field(field,value) # Email cannot be set # if(field == :email) return nil end # Open the file # begin ios=File::open(@full_path+field.to_s,"w") rescue SystemCallError return nil end # Set the value to nil. This is to reflect the # "real" state of the variable (the file has just been # cleared up by the previous call) # @attr_values[field]=nil begin ios.print(value) rescue SystemCallError ios.close return nil end # OK, it worked: assign the new value # ios.close @attr_values[field]=value end def set_flag(flag,value) # NOT DONE YET. Ask the mailing list if I wrote a pile # of crap first... :-| end # TODO: methods to create a new entry (just creates the directory), # methods to get ALL of the parameters in one go in a Hash, etc. end a_subscriber=Subscribers.new() puts a_subscriber.link_to_fs("merc2 / mobily.com") puts a_subscriber.get_field(:email) puts a_subscriber.get_flag(:premium_flag) puts a_subscriber.get_flag(:moderator_flag) puts "OK:" puts a_subscriber.set_field(:name,"BLAH!!!") puts a_subscriber.get_field(:name) ---------------------------------------------------------- Now... here are my questions: * Is it sane for the class to set the class variable @@config_data_dir? @@config_data_dir=IO.read("#{ENV['HOME']}/.subs/ data_dir") * Would it make more sense to create a new person with the method ::new? In this case, what would you call the method to access an existing person? * Is this solution OO sound? I can't think of a way, in Ruby, to do access the information like this: a_subscriber.get_field[:name] or a_subscriber.get_flag [:moderator_flag]. This is the tricky part, and that's where my lack of understanding of OOP shows blatantly. a.subscriber.get_field[:name] is the equivalent of saying a.subscriber.get_field.[](name) This implies that get_field returns an object of some kind able to respond to []. If this were the way to go design-wise (which I doubt, but now I am confused, so...), where would such an object be created? How would it access the class information such as @@config_data_dir, or the subscriber's instance variable? * I am thinking about a container class for this: SubscribersContainer. The class would implement the method each(), so that I can scan through the list of people stored (creating a Subscriber object for iteration). Is this a sane approach? I am just a little scared of doing anything right now. Did I design it all wrong? Should I have created the classes SubscribersFlags and SubscribersAttributes, and have two instance variables in Subscribers derived from SubscribersFlags and SubscribersAttributes? * The most important of all: can you suggest a book or a web site which would help me design more decent classes? Possibly something that is Ruby-centric... Thanks a lot! Merc.