Reputation: 3035
Using awesome_nested_set with Rails 3, I've created a hierarchical categories system. To display the category selector in the view, I've used the following code:
<%= form.select :parent_id, options_for_select(nested_set_options(Category, @category) {|i| "#{'-' * i.level} #{i.name}" }.unshift(["No Parent", nil]), @category.parent_id) %>
I'm attempting to order the categories in alphabetical order, on a level by level basis. If I change the nested_set_options(Category, @category)
to nested_set_options(Category.order("name"), @category)
this will reorder the whole categories list by name; what I want to do is reorder the children of each node alphabetically by name.
For example, I want to resulting select menu to be ordered like this:
Animal
- Bird
-- Chicken
-- Hawk
- Fish
-- Cod
-- Goldfish
-- Trout
- Mammal
-- Cat
-- Primate
--- Chimpanzee
--- Human
-- Zebra
Plant
- Tree
Upvotes: 4
Views: 1715
Reputation: 403
I had the same issue. I solved it as described here. Basically adding the below method to the model that acts_as_nested_set allows you to return a flat array of objects for the select tag in the view by calling @category.sorted_heir_list
:
def sorted_heir_list(target = self, set = self.descendants)
sorted_list = [target]
kids = set.select{|i| i.parent_id == target.id}.sort_by{|j| j.name}
kids.each do |k|
sorted_list.concat(sorted_heir_list(k, set))
end
sorted_list
end
I like this method better than the other answer that I linked in my comment on Morgan Christiansson's answer because it only incurs a single DB hit (vs. N hits with the other approach).
Upvotes: 0
Reputation: 29450
You can use @item.children.except(:order).order("your_sort_column")
as suggested in this stackoverflow post: awesome nested set order by
Upvotes: 1
Reputation: 1062
Although I am unfamiliar with awesome_nested_set, you can call order twice in Rails 3.
Category.order(:level).order(:name)
This should order Category by each level and then by name within each level. Also, you can throw this on the default scope within the model.
class Category < ActiveRecord::Base
default_scope order('level, name')
...
end
Orders are great for default scope because they don't effect any default values.
Upvotes: 2