Nested trees with Ruby on Rails

Jul 29, 2015 - 2 min read
Nested trees with Ruby on Rails

From time to time you get to a point where you want to structure your data in a tree like format. That means you usually want to have some kind of root node that has children and those children could optionally have other children and so on and so forth.

That is what is referred to as the nested set model and depending on preference you might have a left and right field for determining the position of the element in the tree and you could also have a depth field for better performance.

In any case, in Ruby on Rails it’s very easy to use nested sets with the many gems already available like for example (the one I go to every time) awesome_nested_set.

With this gem you only need to include a line in your model and you’re all set.

# Gemfile
gem 'awesome_nested_set'

# config/routes.rb
class CreateCategories < ActiveRecord::Migration
  def self.up
    create_table :categories do |t|
      t.string :name
      t.integer :parent_id, :null => true, :index => true
      t.integer :lft, :null => false, :index => true
      t.integer :rgt, :null => false, :index => true

      # optional fields
      t.integer :depth, :null => false, :default => 0
      t.integer :children_count, :null => false, :default => 0

  def self.down
    drop_table :categories

# app/models/category.rb
class Category < ActiveRecord::Base

So in order to fetch all those children nodes at the bottom of the tree you can use the leaves method provided by the gem.

# We fetch a (random) instance of Category
my_category = Category.first

# Getting the last nodes in the tree (nodes with no children)

If you want to see what other query methods are available, you can check out the Advanced Usage section in the cheatsheet.

12 Project Ideas
Cezar Halmagean
Software development consultant with over a decade of experience in helping growing companies scale large Ruby on Rails applications. Has written about the process of building Ruby on Rails applications in RubyWeekly, SemaphoreCI, and Foundr.