acts_as_tree и has_many: не очень хорошо работают вместе - PullRequest
3 голосов
/ 28 ноября 2011

У меня есть следующее:

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

РЕДАКТИРОВАТЬ # 3 - образец данных семени Вот, например, как будет посев (хотел бы получить и mi_1 и 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

Проблема в том, что я не могу сделать следующее, чтобы вернуть все menu_items:

m=Menu.find(5)
m.menu_items

для has_many: through в Menu.Это позволит получить ТОЛЬКО пункты меню верхнего уровня, а не более глубоких уровней.Я попытался добавить menu_id к menu_headers, но это заставило меня вставить строку commented_out, которая вернула меня к получению только заголовков верхнего уровня.Есть ли способ сказать, дайте мне все более глубокие уровни menu_header, чтобы все вышеперечисленное работало?

Есть ли обходной путь для этого или чего-то еще?Я в значительной степени застрял с act_as_tree, поэтому использование чего-то вроде awesome_nested_set на самом деле не в картах.

thx

EDITS - пара вопросов в комментариях ниже;Я написал это в 4 часа утра

*1019* РЕДАКТИРОВАТЬ # 2
Я могу получить всех детей через это:

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

Я хотел бы иметь возможность вызвать all_children и получить menu_items напункт главного меню.Возможно, интегрируя вышесказанное с вызовом в главном пункте меню, а затем просто сохраняя кэшированную копию в таблице меню, когда будет обновление элемента menu_item.

Посмотрит в Ancestry, но не решается перейти к другому гемутак как другой код зависит от этого.Если бы это можно было сделать быстро, все могло бы быть в порядке, но это довольно сложный объект со многими другими частями, а act_as_tree довольно прост.

Edit # 4 - Вот пример данных:

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 |
+----+----------------------------------------------------+----------------+

ТНХ

Ответы [ 2 ]

0 голосов
/ 28 ноября 2011

Попробуйте это.

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

Это должно дать:

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
0 голосов
/ 28 ноября 2011

Вы можете попробовать родословную , на мой взгляд, это лучше чем activ_as_tree

...