Ruby on Rails associations for set theory (union, difference, intersection, etc.)
I would like a has_many association that works like so:
class Hood acts_as_tree has_many :houses, :union_with => :parent end class House end
where any House associated with Hood 1 would also be returned in .houses of subhoods of Hood 1, along with the subhoods' individual associations.
The association only needs to work from the perspective of the Hood.
I wrote a union_with_parent macro which gave the desired effect, but lots of unfortunate side effects. A major problem was that has_many :dependent => :destroy resulted in unforeseen deletions; deleting a subhood also caused the deletion of all houses in the parent Hood, since I just redefined the houses method.
Similar problem with a set difference macro, except that none of the subhood's houses got destroyed. (Think of this as a mask. So then a subhood would contain all houses in the parent Hood except for those actually listed in the database as belonging to the subhood. The :dependent => :destroy option causes all parent houses to be destroyed, but none of those in the subhood, since we've redefined houses again. The behavior I would want: only the contents of the mask get destroyed.)
I thought about writing a has_many_union macro, but it looks like all of the associations are pretty involved.
Am I doing this stupidly? Is there an easier way? Or should I drastically re-design? (I'd really prefer not to re-design, as transferring the data is not ideal.)
(For the record, yes, I know this metaphor sucks. My actual design wouldn't make sense to most, as it's bioinformatics.)
Maybe you all know of some better way to achieve the desired effect?
You don't want to mix things like :dependent => :destroy with complicated lookups. You could keep your code for .houses, but add a simple has_many association to handle the destroying:
has_many :exclusive_houses, :class_name => 'House', :dependent => 'destroy'
and then build .houses out of .exclusive_houses and parent.houses, or whatever. This will only destroy houses with hood_id of the destroyed hood's id.
Also, just so you know, your example doesn't really make sense with set theory. Elements of a set are included in its superset, not its subsets. If you actually have a nested sets structure, there could be better architectures for that than trees.