From: Robert Klemme Date: 2004-11-18T19:08:14+09:00 Subject: Re: In-memory Relational Data Storage "Robert Klemme" schrieb im Newsbeitrag news:... > > "Curt Sampson" schrieb im Newsbeitrag > news:Pine.NEB.4.58.0411181431440.649@angelic-vtfw.cvpn.cynic.net... > > > > I've been dealing with some slightly more complex groups of data lately. > > Say, something like this: > > > > I have a dozen Libraries. Each library carries some volumes of zero > > or more Journals. For example, Library L1 might have volumes 1-35 of > > Journal J1, and Library L2 might have volumes 25-40 of Journal J1. Each > > Volume has one or more Articles in it, and the same Article might be > > found in multiple Volumes of the same or different Journals. > > > > So I make classes for all of these and started hooking them up together, > > beginning with the obvious tree structure (Libraries reference Journals, > > which reference Volumes, which reference Articles.) But then I realize > > that I had some lookups I wanted to do that needed some different types > > of references, for example, "name all the Journals that have published > > Article A37." > > > > So I start adding more ways of doing efficient lookups, start to worry > about > > various data structures getting out of sync, get some fairly nasty code > > to search down through tree structures, and start to become unhappy. > > > > And then it hits me. The source of all my problems is that, stuck in my > > 'A has a B' reference rut, I've just constructed a hierarchial database, > > which is the source of all my pain. > > > > Well, this is a problem we solved forty years ago when Codd came up with > > the idea of relational databases. So, has anybody built some sort of > > relational storage system for Ruby that will let me describe my data in > > some sort of E/R-ish way and get stuff out from any direction I care to > use? > > You probably just need bidrectional relations plus hashes as indexes. You > could define some utility code that establishes a relation between two > classes and a specialized indexing class that tracks attribute changes > automatically. > > Something along this rough outline: Wait, this is better: require 'set' class Foo; attr_accessor :bar end class Index def initialize(cl, field) name = field.to_sym get_indexes(cl)[name] = self @h = Hash.new {|h,k| h[k]=Set.new} cl.class_eval "def #{field}=(x) idx = self.class::INDEXES[:#{name}]; idx.remove(self, @#{field}); @#{field}=x; idx.add(self, @#{field}) end" end def get_indexes(cl) if cl.const_defined? "INDEXES" cl.const_get "INDEXES" else h = {} cl.const_set "INDEXES", h h end end def add(obj, val) @h[val].add(obj) end def remove(obj, val) @h[val].delete(obj) end def get_all(val) @h[val] end end Index.new(Foo, :bar) f=Foo.new f.bar = 100 Foo::INDEXES[:bar].get_all(100) Regards robert