A place for opinions and notes of a valibuk.

One Model With acts_as_list and acts_as_tree

Tagged with: — ondrej at 8:49 pm on Sunday, February 4, 2007

Ruby on Rails Ruby on Rails provides nice ways to create a list (acts_as_list), that is to keep order of items, and to create a tree (acts_as_tree), that is to organise items with parent–children relationships. But what to do, if you need both functionalities at once?

My model has name Outline and it holds one textual information.

Firstly we will create a model and its migration:


The output should be:

  1. exists  app/models/
  2. exists  test/unit/
  3. exists  test/fixtures/
  4. create  app/models/outline.rb
  5. create  test/unit/outline_test.rb
  6. create  test/fixtures/outlines.yml
  7. create  db/migrate
  8. create  db/migrate/001_create_outlines.rb

The next two sections describe how to modify the generated migration and model files.


The migration is stored in the generated file db/migrate/001_create_outlines.rb. Of course, if you already created some migrations, the 001 number will be higher.

The model (and the table too) has to contain columns: parent_id for the acts_as_tree declaration, position for the acts_as_list declaration and name to hold textual data.

The content of the migration with three new columns:


Do not forget to apply the new migration:

  1. rake db:migrate

This part was simple — the main part of the magic is in the model file…


The model is stored in the generated file app/models/outline.rb.

Let’s add all necessary parts for acts_as_list and acts_as_tree declarations and mix them up gently (thanks to Kris for noticing):

  1. span style=”color:#996600;”>"position"

That is it :)


Here are an example, how it works (it is a modified output from ruby script/console):

  1. #testing of the list features
  2. "first" #create an instance with name "first"
  3. => #…
  4. #its position is 1
  5. "second" #create another instance with name "second"
  6. => #…
  7. #its position is 2
  8. => 2
  9. o2.move_higher #move second item higher
  10. #it is on the top; its position is 1
  11. #it is necessary to reload it to reflect the previous change
  12. => #…
  13. #testing of the tree features
  14. "first’s child" #let’s create a child
  15. => #…
  16. o1.children << o11 #assign it to its parent
  17. => [#…]
  18. #the position is 1, because it is the first child of "first"
  19. #what is the parents name? should be "first"
  20. => "first"#what are the children names?
  21. first’s child
  22. => [#…]

I hope it will help you. Enjoy

This is the previous version of the model that Kris mentioned in his comment.

  1. span style=”color:#996600;”>"Outline""Outline""parent_id""position""position"
These icons link to social bookmarking sites where readers can share and discover new web pages.
  • DZone
  • Digg
  • Reddit
  • Technorati
  • Furl
  • NewsVine
  • Slashdot
  • Ma.gnolia
  • StumbleUpon


Comment by Kris

May 17, 2007 @ 12:58 pm

I was wondering why you need the belongs_to & has_many (which look like they provide a self-referential HABTM relationship) if you are using acts_as_tree, does acts_as_tree not already provide this functionality?

Comment by ondrej

May 17, 2007 @ 5:06 pm

Hi Kris,

You are right, I will change it…

Thank you :)


Comment by ondrej

May 17, 2007 @ 5:07 pm

Btw. I added several lines to the example to show that is necessary to reload other instances to reflect a change of the order.

Comment by Rob

September 12, 2007 @ 3:23 pm

Cheers for the write up, there’s not much on this considering how useful it is! Nice one.

Comment by linoj

October 12, 2007 @ 3:43 am

hi, for a detailed application of this

Comment by si

June 4, 2008 @ 11:42 pm

For a more efficient and elegant solution to mixing AAT and AAL, look at awesome nested set on Github.

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Comment Preview

commercial break :)

Make an account on -- a really good hosting where you have your own virtual machine. I installed Gentoo there = I like it very much ;)