I have the following:
class Menu < ActiveRecord::Base
has_many :menu_headers
# has_many :menu_headers, :conditions => {:parent_id => 0} - was trying
# to set parent_id to 0 for top level
has_many :menu_items, :through => :menu_headers
end
class MenuHeader < ActiveRecord::Base
belongs_to :menu
has_many :menu_items
acts_as_tree
end
class MenuItem < ActiveRecord::Base
#belongs_to :menu
has_one :menu, :through => :menu_header
belongs_to :menu_header
end
EDIT #3 - seed data sample Here is for example, how would be seeding (would like to get both mi_1 and mi_2)
m_1=Menu.create({:name => "Dinner Menu test", :location_id => 145})
c_1=m_1.menu_headers.create({:name => "White Wine"})
c_2=c_1.children.create({:name => "Sauvignon Blanc"})
mi_1=c_2.menu_items.create({:header => "SB menu item #1"})
mi_2=c_1.menu_items.create({:header => "SB menu item #2"})
m_1.menu_items # returns only mi_2; would like both mi_2 and mi_1
end EDIT #3
The problem is that I can't do the following to return all the menu_items:
m=Menu.find(5)
m.menu_items
for the has_many :through in Menu. This will get ONLY the menu-items of the top-level and not deeper levels. I tried add menu_id to the menu_headers but this forced me to put in the commented_out line which got me back to only getting the top level headers. Is there a way to say get me all the deeper levels of the menu_header so that the above works?
Is there a workaround to this or something else? I'm pretty much stuck with acts_as_tree so using something like awesome_nested_set isn't really in the cards.
thx
EDITS - a couple of issues in the comments below; I wrote this at 4am
EDIT #2
I am able to get all children via this:
class MenuHeader < ActiveRecord::Base
...
# only gets all children of the current menu_header_id
def all_children
all = []
self.children.each do |menu_header|
all << menu_header
root_children = menu_header.all_children.flatten
all << root_children unless root_children.empty?
end
return all.flatten
end
end
I would like to be able to call all_children and get menu_items on the main Menu item. Perhaps integrating the above with a call on the main Menu item and then just storing a cached copy in the menus table when there is an update to a menu_item.
Will look into Ancestry but am hesitant to move to another gem since other code is dependent on this. If could be done quickly, might be ok but this is a fairly complex object with many other pieces and acts_as_tree is fairly straightforward.
Edit #4 - Here is sample data:
menus
+----+-------------+------------------+
| id | location_id | name |
+----+-------------+------------------+
| 1 | 145 | item cocktails |
+----+-------------+------------------+
menu_headers
+----+----------------------+-----------+---------+
| id | name | parent_id | menu_id |
+----+----------------------+-----------+---------+
| 1 | Wines By The Glass | 0 | 1 |
| 2 | WHITE WINES | 1 | NULL |
| 3 | WHITE WINES child #1 | 2 | NULL |
| 4 | WHITE WINES child #2 | 2 | NULL |
| 5 | WHITE WINES child #3 | 2 | NULL |
| 6 | RED WINES | 0 | 1 |
+----+----------------------+-----------+---------+
menu_items
+----+----------------------------------------------------+----------------+
| id | header | menu_header_id |
+----+----------------------------------------------------+----------------+
| 1 | SAUVIGNON BLANC item #1 | 2 |
| 2 | MONTEPULCIANO | 6 |
+----+----------------------------------------------------+----------------+
thx
Try this.
class Menu < ActiveRecord::Base
has_many :menu_headers, :conditions => {:parent_id => 0}
has_many :menu_sub_headers, :class_name => 'MenuHeader'
has_many :menu_items, :through => :menu_sub_headers
end
class MenuHeader < ActiveRecord::Base
belongs_to :menu
has_many :menu_items
acts_as_tree
end
class MenuItem < ActiveRecord::Base
has_one :menu, :through => :menu_header
belongs_to :menu_header
end
That should give:
m1=Menu.create(:name => "Dinner Menu test", :location_id => 145)
c1=m1.menu_headers.create(:name => "White Wine")
c2=c1.children.create(:name => "Sauvignon Blanc", :menu => m1)
mi1=c2.menu_items.create(:header => "SB menu item #1")
mi2=c1.menu_items.create(:header => "SB menu item #2")
m_1.menu_items # should return mi1 and mi2
m_1.menu_headers # should return just c1
m_1.menu_sub_headers # should return c1 and c2