Reputation: 44066
Ok so i have a pages table with all the static with this schema
create_table "pages", :force => true do |t|
t.string "name"
t.text "html"
t.string "url"
t.integer "position"
t.boolean "is_home"
t.integer "parent_id", :default => 0, :null => false
t.string "nav"
end
A page can have another page as its parent. The idea is that I want the user to have complete control of the navigation and the pages. So my question what is the best way to group these pages so in the html i can loop over all the pages and their subpages
Here is what i have so far
grouped_pages = Page.where(:is_home => 0).group_by(&:nav).each do |key, group|
group.sort_by(&:parent_id)
end
I was hoping to group them in some array and or hash combination with another layer for ever page that has a parent_id of another page
the page structure can look like this
Page1
Page3
Page7
Page4
Page5
Page2
Page5
Page6
Any ideas of the best way to sort and loop over to print out the uls for the html
Upvotes: 1
Views: 571
Reputation: 16435
With a gem like closure tree you can have the same basic tree behavior, plus all the following:
and many others, implemented so to execute only one query.
(See http://matthew.mceachen.us/blog/tags/closure-tree for reasons behind such a tree.)
Upvotes: 1
Reputation: 67880
If you want to allow arbitrarily nested tree levels, the easiest solution is a recursive algorithm. For example (uses parent_id = NULL
, not 0, for the page root):
class Page < ActiveRecord::Base
belongs_to :parent, :class_name => :Page
has_many :children, :class_name => :Page, :foreign_key => :parent_id
def self.root
where(:parent => nil).first
end
def tree
[self, children.map(&:tree)]
end
end
Page.root.tree
#=> returns the structure in pairs [page, children]
From this you can do whatever you need. For exemple, to set a sort criterion, just add an options argument to tree
and use it to scope children
.
Note that to render a tree structure you also need a recursive helper to perform the task. In fact probably you don't need this tree
method, just a recursive helper that calls children
, but the idea is the same.
As Mark points out, there are gems to implement AR trees, for example acts_as_tree.
Upvotes: 3