"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag news:...
"Curt Sampson" <cjs@cynic.net> 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:
<snip/>
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