Belongs_to multiple things

I am wondering what the best way to go about this situation is from a
design perspective:

A has many Cs. A has many Bs. B has many Cs.

Example (not the example from my real app, so hopefully it makes sense).

We have restaurants. Each restaurant has many menus. Each restaurant
has many dishes. Every dish /must/ belong to a menu, and every dish
/must/ belong to a restaurant (conceptually). The same dish cannot
belong to 2 different menus or restaurants (a dish with all the same
attributes could, but in the DB its a different dish).

As it is often useful to find all given dishes for a given restaurant
that match some criteria, it is tempting to do this:

class Restaurant
has_many :dishes
has_many :menus
end

class Menu
has_many :dishes
end

class Dish
belongs_to :restaurant
belongs_to :menu
end

But this seems somehow bad. I know that it makes deletions work
strangely (the item can be deleted from the restaurant and still found
on one of its menus, etc. So right now I am doing it like this:

Class Restaurant
has_many :menus
def dishes
my_dishes = []
menus.each do |menu|
menu.dishes.each do |dish|
my_dishes.push dish
end
end
end
my_dishes
end

Class Menu
has_many :dishes
end

Class Dish
belongs_to :menu
end

Which works well enough, but given_restaurant.dishes now returns an
array, so I cannot call ActiveRecord methods on it,
(some_restaurant.dishes.find(:all, :conditions {:course => “entree”}) )
which is sometimes inconvenient.

It seems like a fairly common scenario to have A has many Bs and B has
many Cs, and to want to be able to efficiently access the Cs from A, so
I was wondering if there was a railsier, DRYer way to go about this.
Any hints/ideas/tutorial links?

Nick G. wrote:

We have restaurants. Each restaurant has many menus. Each restaurant
has many dishes. Every dish /must/ belong to a menu, and every dish
/must/ belong to a restaurant (conceptually). The same dish cannot
belong to 2 different menus or restaurants (a dish with all the same
attributes could, but in the DB its a different dish).

I could be misreading your design specifications here, but it seems to
me that restaurants would have many dishes through menus:

class Restaurant
has_many :menus, :dependent => :destroy
has_many :dishes, :through => :menus
end

class Menu
belongs_to :restaurant
has_many :dishes, :dependent => :destroy
end

class Dish
belongs_to :menu
end

Then you could do things like:
restaurant.menus
restaurant.dishes
menu.dishes
dish.menu.restaurant

Precisely what I’m looking for. I thought I must be missing something,
somehow reading books/tutorials all at once my brain just lets some
information go, and I couldn’t remember the pertinent info, but I could
tell my way was not “railsish”.

Sorry for the silly question and thanks for the answer :slight_smile:

Robert W. wrote:

Nick G. wrote:

We have restaurants. Each restaurant has many menus. Each restaurant
has many dishes. Every dish /must/ belong to a menu, and every dish
/must/ belong to a restaurant (conceptually). The same dish cannot
belong to 2 different menus or restaurants (a dish with all the same
attributes could, but in the DB its a different dish).

I could be misreading your design specifications here, but it seems to
me that restaurants would have many dishes through menus:

class Restaurant
has_many :menus, :dependent => :destroy
has_many :dishes, :through => :menus
end

class Menu
belongs_to :restaurant
has_many :dishes, :dependent => :destroy
end

class Dish
belongs_to :menu
end

Then you could do things like:
restaurant.menus
restaurant.dishes
menu.dishes
dish.menu.restaurant

Thanks for asking the question, it helped me understand things better.

On Sep 10, 1:52 am, Nick G. [email protected]