• Stars
    star
    2,376
  • Rank 18,581 (Top 0.4 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 16 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An awesome replacement for acts_as_nested_set and better_nested_set.

Awesome Nested Set

CI Code Climate

Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is a replacement for acts_as_nested_set and BetterNestedSet, but more awesome.

Older versions: Version 3.2 supports Rails 6, 3.1 supports Rails 5 & 4. Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.

What makes this so awesome?

This is a new implementation of nested set based off of BetterNestedSet that fixes some bugs, removes tons of duplication, adds a few useful methods, and adds STI support.

Installation

Add to your Gemfile:

gem 'awesome_nested_set'

Usage

To make use of awesome_nested_set your model needs to have 3 fields: lft, rgt, and parent_id. The names of these fields are configurable. You can also have optional fields: depth and children_count. These fields are configurable. Note that the children_count column must have null: false and default: 0 to function properly.

class CreateCategories < ActiveRecord::Migration
  def change
    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
      t.timestamps
    end
  end
end

Enable the nested set functionality by declaring acts_as_nested_set on your model

class Category < ActiveRecord::Base
  acts_as_nested_set
end

Run rake rdoc to generate the API docs and see CollectiveIdea::Acts::NestedSet for more information.

Options

You can pass various options to acts_as_nested_set macro. Configuration options are:

  • parent_column: specifies the column name to use for keeping the position integer (default: parent_id)
  • primary_column: specifies the column name to use as the inverse of the parent column (default: id)
  • left_column: column name for left boundary data (default: lft)
  • right_column: column name for right boundary data (default: rgt)
  • depth_column: column name for the depth data default (default: depth)
  • scope: restricts what is to be considered a list. Given a symbol, it'll attach _id (if it hasn't been already) and use that as the foreign key restriction. You can also pass an array to scope by multiple attributes. Example: acts_as_nested_set :scope => [:notable_id, :notable_type]
  • dependent: behavior for cascading destroy. If set to :destroy, all the child objects are destroyed alongside this object by calling their destroy method. If set to :delete_all (default), all the child objects are deleted without calling their destroy method. If set to :nullify, all child objects will become orphaned and become roots themselves.
  • counter_cache: adds a counter cache for the number of children. defaults to false. Example: acts_as_nested_set :counter_cache => :children_count
  • order_column: on which column to do sorting, by default it is the left_column_name. Example: acts_as_nested_set :order_column => :position
  • touch: If set to true, then the updated_at timestamp on the ancestors will be set to the current time whenever this object is saved or destroyed (default: false)

See CollectiveIdea::Acts::NestedSet::Model::ClassMethods for a list of class methods and CollectiveIdea::Acts::NestedSet::Model for a list of instance methods added to acts_as_nested_set models

Indexes

It is highly recommended that you add an index to the rgt column on your models. Every insertion requires finding the next rgt value to use and this can be slow for large tables without an index. It is probably best to index the other fields as well (parent_id, lft, depth).

Callbacks

There are three callbacks called when moving a node: before_move, after_move and around_move.

class Category < ActiveRecord::Base
  acts_as_nested_set

  after_move :rebuild_slug
  around_move :da_fancy_things_around

  private

  def rebuild_slug
    # do whatever
  end

  def da_fancy_things_around
    # do something...
    yield # actually moves
    # do something else...
  end
end

Beside this there are also hooks to act on the newly added or removed children.

class Category < ActiveRecord::Base
  acts_as_nested_set  :before_add     => :do_before_add_stuff,
                      :after_add      => :do_after_add_stuff,
                      :before_remove  => :do_before_remove_stuff,
                      :after_remove   => :do_after_remove_stuff

  private

  def do_before_add_stuff(child_node)
    # do whatever with the child
  end

  def do_after_add_stuff(child_node)
    # do whatever with the child
  end

  def do_before_remove_stuff(child_node)
    # do whatever with the child
  end

  def do_after_remove_stuff(child_node)
    # do whatever with the child
  end
end

Protecting attributes from mass assignment (for Rails < 4)

It's generally best to "whitelist" the attributes that can be used in mass assignment:

class Category < ActiveRecord::Base
  acts_as_nested_set
  attr_accessible :name, :parent_id
end

If for some reason that is not possible, you will probably want to protect the lft and rgt attributes:

class Category < ActiveRecord::Base
  acts_as_nested_set
  attr_protected :lft, :rgt
end

Add to your existing project

To make use of awesome_nested_set, your model needs to have 3 fields: lft, rgt, and parent_id. The names of these fields are configurable. You can also have optional fields, depth and children_count.

Create a migration to add fields:

class AddNestedToCategories < ActiveRecord::Migration

  def self.up
    add_column :categories, :parent_id, :integer # Comment this line if your project already has this column
    # Category.where(parent_id: 0).update_all(parent_id: nil) # Uncomment this line if your project already has :parent_id
    add_column :categories, :lft,       :integer
    add_column :categories, :rgt,       :integer

    # optional fields
    add_column :categories, :depth,          :integer
    add_column :categories, :children_count, :integer

    # This is necessary to update :lft and :rgt columns
    Category.reset_column_information
    Category.rebuild!
  end

  def self.down
    remove_column :categories, :parent_id
    remove_column :categories, :lft
    remove_column :categories, :rgt

    # optional fields
    remove_column :categories, :depth
    remove_column :categories, :children_count
  end

end

Enable the nested set functionality by declaring acts_as_nested_set on your model

class Category < ActiveRecord::Base
  acts_as_nested_set
end

Your project is now ready to run with the awesome_nested_set gem!

Conversion from other trees

Coming from acts_as_tree or another system where you only have a parent_id? No problem. Simply add the lft & rgt fields as above, and then run:

Category.rebuild!

Your tree will be converted to a valid nested set. Awesome!

Note: You can use Category.rebuild!(false) to skip model validations when performing the rebuild.

View Helper

The view helper is called #nested_set_options.

Example usage:

<%= f.select :parent_id, nested_set_options(Category, @category) {|i| "#{'-' * i.level} #{i.name}" } %>

<%= select_tag 'parent_id', options_for_select(nested_set_options(Category) {|i| "#{'-' * i.level} #{i.name}" } ) %>

See CollectiveIdea::Acts::NestedSet::Helper for more information about the helpers.

How to contribute

Please see the 'Contributing' document.

Copyright © 2008–2015 Collective Idea, released under the MIT license.

More Repositories

1

interactor

Interactor provides a common interface for performing complex user interactions.
Ruby
3,313
star
2

audited

Audited (formerly acts_as_audited) is an ORM extension that logs all changes to your Rails models.
Ruby
3,300
star
3

json_spec

Easily handle JSON in RSpec and Cucumber
Ruby
921
star
4

interactor-rails

Interactor Rails provides Rails support for the Interactor gem.
Ruby
432
star
5

delayed_job_active_record

ActiveRecord backend integration for DelayedJob 3.0+
Ruby
340
star
6

graticule

Graticule is a geocoding API for looking up address coordinates and performing distance calculations, supporting many popular APIs.
Ruby
299
star
7

tinder

Tinder is a Ruby API for interfacing with Campfire, the 37Signals chat application.
Ruby
258
star
8

inside_the_machine

HTML
256
star
9

acts_as_geocodable

Simple geocoding for Active Record models
Ruby
206
star
10

delayed_job_mongoid

Mongoid backend for delayed_job
Ruby
171
star
11

action_mailer_optional_tls

Enables TLS on SMTP connections (for services like GMail)
Ruby
127
star
12

command

Command provides a simple object-oriented interface for running shell commands from Ruby.
Ruby
93
star
13

sunspot_test

Auto-starts solr for your tests
Ruby
55
star
14

devise-mongo_mapper

MongoMapper ORM for Devise
Ruby
49
star
15

awesomeness

Collective Idea's Awesomeness. A collection of useful Rails bits and pieces.
Ruby
47
star
16

unicode_math

Fun Ruby extensions for doing math with Unicode
Ruby
47
star
17

acts_as_money

an Active Record plugin that makes it easier to work with the money gem
Ruby
45
star
18

calendar_builder

Ruby
45
star
19

caldav

A Ruby CalDAV client
Ruby
39
star
20

awesome-backup

Rails plugin that provides Rake and Capistrano tasks for making database backups
Ruby
32
star
21

merger

A gem for merging Active Record models
Ruby
30
star
22

html5

A Rails plugin for playing around with HTML5.
Ruby
29
star
23

with_action

A respond_to style helper for doing different actions based on which request parameters are passed.
Ruby
24
star
24

ARPlaneDetector

Use ARKit to find, and visualize horizontal and vertical planes.
Swift
23
star
25

CollectionGraph

Beautiful graphs made with UICollectionViews
Swift
23
star
26

rubymotion-parsedotcom-chat

A simple chat application written with RubyMotion and using Parse.com
Ruby
19
star
27

delayed_job_data_mapper

DataMapper backend for delayed_job
Ruby
16
star
28

deploy_and_deliver

Capistrano recipes for Pivotal Tracker. Can mark stories delivered on deploy.
Ruby
15
star
29

random_finders

A Rails plugin that allows quick and easy fetching of random records, or records in random order.
Ruby
14
star
30

searchparty

Simple site that aggregates Google, Delicious, and GitHub searches. See http://search.collectiveidea.com
JavaScript
13
star
31

pivotal_tracker

ActiveResource wrapper around v3 of the Pivotal Tracker API
Ruby
13
star
32

unifi

A ruby client for the (undocumented) Unifi AP Controller API
Ruby
12
star
33

measurement

A sweet Ruby measurement & converstion Library.
Ruby
12
star
34

clear_empty_attributes

When Active Record objects are saved from a form, empty fields are saved as empty strings instead of nil. This kills most validations.
Ruby
11
star
35

travis_bundle_cache

DEPRECATED: Cache the gem bundle for speedy travis builds (Travis now handles this)
Ruby
10
star
36

seinfeld.sh

Show the date of your last commit when logging into a terminal according to Calendar About Nothing
Shell
10
star
37

fireside

Open Source Chat
Ruby
10
star
38

bender

Ruby
9
star
39

tweet-wall

A Twitter visualizer
JavaScript
8
star
40

buildlight

Aggregating webhooks from multiple build services (Travis, Circle, Heroku) to power the stoplight in our office.
Ruby
8
star
41

chat

An example chat application
Ruby
7
star
42

yardvote.com

Tracking political yard signs.
Ruby
7
star
43

simple-maps

Add Google Maps in seconds. Maps any and all hCards on the page and resizes the map to fit. Uses the new Google Maps JavaScript API v3. It will even do the geocoding for you!
JavaScript
7
star
44

metrics

A tool for tracking arbitrary metrics via Slack
Ruby
6
star
45

rails_relay_authentication

Ruby
6
star
46

capybara-ui

Page objects for readable, resilient acceptance tests
Ruby
6
star
47

twirp-kmm

Twirp service generator and runtime for Kotlin Multiplatform Mobile projects.
Kotlin
6
star
48

rubymotion-drawing

Quick and dirty drawing app written with RubyMotion
Ruby
6
star
49

statsite-instrumental

Statsite Sink for Instrumental
Go
5
star
50

audit-demo

Demo application for acts_as_audited
5
star
51

migration_test_helper

Ruby
5
star
52

hourglass

Client and internal time management with Harvest
Ruby
5
star
53

acts_as_audited

acts_as_audited is now… Audited.
5
star
54

imap_authenticatable

Authenticate your Rails app using any IMAP server!
Ruby
5
star
55

rosie

CoffeeScript
4
star
56

playing-with-sunspot

A demo of sunspot and solr
Ruby
4
star
57

perfecttime

Mike West's PerfectTime.js, with a few updates.
JavaScript
4
star
58

git-access

Secure access to hosted git repositories
Go
4
star
59

pivotalharvest

Ruby
4
star
60

recursable

Some helpers for using trees in Rails
Ruby
3
star
61

integrity-nabaztag

An Integrity notifier for Nabaztag
Ruby
3
star
62

adapter-simpledb

An adapter for Amazon's SimpleDB
Ruby
3
star
63

data-loss

Tracking when things happened.
Ruby
3
star
64

eharbor

Example Rails application for Ruby on Rails training used by Collective Idea and Idea Foundry (http://ideafoundry.info/ruby-on-rails). Note: we often use interactive rebases, so commit dates may not make sense.
Ruby
3
star
65

pgbackups_archive_app

A very simple app to archive PGBackups to S3.
Ruby
3
star
66

ios-swifter-example

Using Swifter to stub network calls
Swift
3
star
67

twitter

A Twitter clone used for training
Ruby
2
star
68

collective-data

Gem for pulling data from the CollectiveData website
Ruby
2
star
69

get-to-work-go

Start and stop project specific, annotated Harvest timers with information from Pivotal Tracker
Go
2
star
70

dm-mongo-adapter

2
star
71

ember-helpers

A collection of handlebars helpers for Ember.js
JavaScript
2
star
72

example_of_sunspot_test

A rails 3 codebase showing the usage of sunspot_test
Ruby
2
star
73

jquery.defaulttext

jQuery plugin to set the default text of an input using the title element
JavaScript
2
star
74

over_board

Ruby
2
star
75

test-kitchen-provisioners

A collection of test-kitchen provisioners (https://github.com/opscode/test-kitchen)
Ruby
2
star
76

namecase

Ruby
2
star
77

sunspot-indexing-strategies

A Rails 3 codebase that uses Sunspot to show how you can search search within words.
Ruby
2
star
78

mephisto-comment-notification

A simple comment notification plugin for the Mephisto blogging engine.
Ruby
2
star
79

mintastic

A Mint to QIF converter that also functions as a Rails + React + Redux tutorial app
Ruby
2
star
80

react-ujs-rails

React UJS package for rails, extracted from react-rails
JavaScript
1
star
81

mephisto_atompub

AtomPub plugin for mephisto
Ruby
1
star
82

donuts-android

Android client for donuts.collectiveidea.com
Kotlin
1
star
83

cucumber-web

Reusable web steps for Cucumber and Capybara
Ruby
1
star
84

laketown

Calculate what you could save on internet service in Laketown Township
HTML
1
star
85

cucumber_slices

Cucumber steps that we use often
Ruby
1
star
86

donuts

Collective Idea Donut Tracker
Ruby
1
star
87

donuts-ios

iOS Client for donuts.collectiveidea.com
Swift
1
star
88

rubocop-config

Working toward a rubocop config we all can agree on.
1
star
89

build-test

Stupid simple way to test a continuous integration build server.
Shell
1
star
90

get_to_work

A rubygem to tag your Harvest time entries with Pivotal Tracker Information
Ruby
1
star
91

no-phone

Not a phone.
Ruby
1
star
92

delayed_job_example

An example app for using Delayed Job
Ruby
1
star
93

finish_weekend

Finish Weekend
Ruby
1
star