From: Christoph Date: 2002-09-24T03:38:36+09:00 Subject: Re: self as method argument revisited wrote in message news:Pine.LNX.4.44.0209230931170.7789-100000@candle.superlink.net... > Hi -- > > On Mon, 23 Sep 2002, Christoph wrote: > > > dblack wrote > > .... > > > A while ago transami brought up the question of an object needing > > > access to the object that created it, and there was discussion of > > > techniques including sending self as an argument. I've been working > > > on a case of the underlying problem he was talking about, and I > > > thought I'd share my (current) solution. Comments welcome. > > > > > > The big object is a (simple) database image. It creates Row objects > > > from arguments to an #insert method, and populates itself hash-wise > > > with the values. > > > > > > There are also field names. A Row object needs to know its own field > > > names, so that one can do things like: > > > > > > r = db["Black"] # r is a Row object > > > r["first_name"] # => David > > > > > > Originally I had been creating an array of field names for every row, > > > but that seemed very clunky. Then I got an idea.... > > > > > > When the database object is created, it creates a new class, which > > > inherits from an existing Row class (DBDBD::Row). That new class has > > > an instance variable (i.e., its virtual class defines an accessor > > > method) called @row_class. The new database object assigns itself to > > > @db in that Row class's virtual class: > > > > While I am still marveling what problem your are trying to solve - > > I am sort of wandering why you are creating a Row constant in > > the scope of the meta (virtual) class of every DBDB instance? > > I doubt hat you woould ever make use of this constant, unless > > your are planning on peppering every DBDB instance with a > > barrage of singleton methods. > > Don't marvel -- I may well be on the wrong track :-) I'm not sure I > understand what you're saying, though. My thinking is: each database > (DBDB instance) needs to create rows, and those rows need to know how > to send messages to the database. Since I don't want to put that > knowledge in a static Row class (since different databases will have > different fields), I thought it would make sense to have a separate > Row class for every database. > > > > > --- > > class DBDB # The 1.6 object model is inferior > > def initialize(...) > > ... > > @row_class = Class.new (DBDBD::Row) > > class << @row_class > > attr_accessor :db > > end > > @row_class.db = self > > end > > ... > > end > > > > > > class DBDB # 1.7 version > > class Row > > ... > > @row_class = self > > class << self > > attr_accessor :db > > end > > end > > def initialize(...) > > ... > > @row_class = Class.new (DBDBD::Row) > > @row_class.db = self > > end > > ... > > end > > In your next post you change that to @row_class.db = nil. But isn't > self correct? The idea is for the Row class's db attribute to contain > a reference to this data base object. Probably the correct line would (could?) have been `` @db = nil''. The ``problem'' with our version is it forces the creation (instantiation) of the (virtual) meta class for every DBDB object without making any apparent use of this fact. Here the a more complete version (it should work 1.6 - i.e. I got my self tangled up in the usual self, meta, whatever class loop;-) . --- class DBDB class Row # ... @db = nil class << self attr_accessor :db def inspect unless equal? Row "#" else super end end alias to_s inspect end end def initialize #(...) # ... @row_class = Class.new Row @row_class.db = self end end p DBDB.new #)>> --- /Christoph /Ps The news gate was clocked up yesterday so I only got to read your answer to Tom's email today . The general problem I see with this approach is that one also needs to tune many standard methods like clone,dup, ... and possibly class methods like inherited, _load etc.