views:

193

answers:

1

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?

+1  A: 

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.

mckeed
Apologies, you are correct. It should have been a superhood. =)
mohawkjohn