3

Im using the awesome nested set plugin for ruby on rails. How do I go about sorting by like :name column or something ?

Currently shows the tree like

A
- C
- B

I want it like

A
- B
- C
Andrew Cetinic
  • 2,763
  • 24
  • 44

5 Answers5

7

Doing this overrides the database sort:

@item.children.except(:order).order("your_sort_column")

Example:

organization.self_and_descendants.to_sql
=> "SELECT `organizations`.* FROM `organizations`  WHERE (`organizations`.`lft` >= 1 AND `organizations`.`lft` < 54) ORDER BY `organizations`.`lft`" 

organization.self_and_descendants.except(:order).order("organization_nm").to_sql
=> "SELECT `organizations`.* FROM `organizations`  WHERE (`organizations`.`lft` >= 1 AND `organizations`.`lft` < 54) ORDER BY organization_nm" 
Eric K
  • 395
  • 2
  • 8
4

Unfortunately it's impossible now. In their class written that "odering by an other column than lft does not work" (lib/awesome_nested_set.rb)

kr00lix
  • 3,214
  • 1
  • 16
  • 11
  • 2
    2 and a bit years later, this seems to still be the case? – gef Jan 24 '13 at 18:07
  • 2
    what about 3 years later? – Gediminas Jan 18 '14 at 07:47
  • 3
    For what it's worth, I was able to do a database sort with this: @item.children.except(:order).order("your_sort_column") – Eric K Feb 05 '14 at 16:22
  • 1
    In my opinion, not implement position behavior is like create bike without pedals. You can ride, but not so much :D What guys you are using for standart website navigation? It seems there is no decision in Rails with tree behavior and positions. – Gediminas Apr 04 '14 at 15:27
2

Already implemented in awesome_nested_set

order_column: on which column to do sorting, by default it is the left_column_name. Example: acts_as_nested_set :order_column => :position

and closure_tree

If you want a specific order, add a new integer column to your model in a >migration:

t.integer :sort_order

and in your model:

class OrderedTag < ActiveRecord::Base
  has_closure_tree order: 'sort_order'
end
askrynnikov
  • 343
  • 4
  • 10
1

I confirm what @kr00lix said. My way to bypass that problem :

@item_children = @item.children
@item_children = @item_children.sort_by!(&:your_sort_column)

But I agree that in order to avoid useless memory consumption, it would be much nicer to set the order in the SQL command directly.

David
  • 46
  • 3
0

I was able to do this in Rails with recursion:

def add_self_and_children
  [self, children.sort_by{|e| e.name}.map{|c| c.add_self_and_children}].flatten
end

Then call Model.root.add_self_and_children.

But obviously this involves a series of massive database hits.

So if someone who knows more about SQL recursion than I wants to convert this to pure SQL, that would be magic!

BTW, for some reason the following, which would have been a little kinder on the database, did not work:

def add_self_and_children
  [self, children.order(:name).map{|c| c.add_self_and_children}].flatten
end
steven_noble
  • 3,945
  • 10
  • 41
  • 77