acts_as_tree 和 has_many :由于不能很好地协同工作

发布于 2024-12-18 09:40:25 字数 3317 浏览 2 评论 0原文

我有以下内容:

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

结束编辑 #3

问题是我无法执行以下操作来返回所有 menu_items:

m=Menu.find(5)
m.menu_items

对于菜单中的 has_many :through 。这将仅获得顶级菜单项,而不是更深级别的菜单项。我尝试将 menu_id 添加到 menu_headers 中,但这迫使我放入 commented_out 行,这让我只能获取顶级标题。有没有办法让我了解 menu_header 的所有更深层次,以便上面的工作正常?

有解决方法吗?我几乎坚持使用acts_as_tree,所以使用awesome_nested_set之类的东西并不是真正可行的。

谢谢

编辑 - 下面评论中的几个问题;我在凌晨 4 点写的

编辑 #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,但我犹豫是否要转移到另一个 gem,因为其他代码依赖于此。如果可以快速完成,可能没问题,但这是一个相当复杂的对象,有许多其他部分,并且acts_as_tree相当简单。

编辑 #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 |
+----+----------------------------------------------------+----------------+

thx

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

这样的小城市 2024-12-25 09:40:25

试试这个。

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

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
近箐 2024-12-25 09:40:25

你可以尝试ancestry,在我看来它比acts_as_tree更好

You can try ancestry, in my opinion it's better than acts_as_tree

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文