{"id":13462911,"url":"https://github.com/collectiveidea/awesome_nested_set","last_synced_at":"2025-05-14T07:04:40.297Z","repository":{"id":383723,"uuid":"912","full_name":"collectiveidea/awesome_nested_set","owner":"collectiveidea","description":"An awesome replacement for acts_as_nested_set and better_nested_set.","archived":false,"fork":false,"pushed_at":"2024-11-14T18:49:22.000Z","size":667,"stargazers_count":2411,"open_issues_count":4,"forks_count":487,"subscribers_count":40,"default_branch":"main","last_synced_at":"2025-05-07T06:17:25.541Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/collectiveidea.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["parndt"]}},"created_at":"2008-02-21T16:03:25.000Z","updated_at":"2025-04-24T16:02:28.000Z","dependencies_parsed_at":"2023-07-05T14:43:48.822Z","dependency_job_id":"d237eec4-3b4d-49da-9074-9130813ef627","html_url":"https://github.com/collectiveidea/awesome_nested_set","commit_stats":{"total_commits":486,"total_committers":139,"mean_commits":"3.4964028776978417","dds":0.8395061728395061,"last_synced_commit":"3913eca5981ec60662985fe39adf988eb5c2731d"},"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collectiveidea%2Fawesome_nested_set","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collectiveidea%2Fawesome_nested_set/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collectiveidea%2Fawesome_nested_set/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collectiveidea%2Fawesome_nested_set/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/collectiveidea","download_url":"https://codeload.github.com/collectiveidea/awesome_nested_set/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092648,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T13:00:40.780Z","updated_at":"2025-05-14T07:04:40.231Z","avatar_url":"https://github.com/collectiveidea.png","language":"Ruby","readme":"# Awesome Nested Set\n\n[![CI](https://github.com/collectiveidea/awesome_nested_set/actions/workflows/ci.yml/badge.svg)](https://github.com/collectiveidea/awesome_nested_set/actions/workflows/ci.yml) [![Code Climate](https://codeclimate.com/github/collectiveidea/awesome_nested_set.svg)](https://codeclimate.com/github/collectiveidea/awesome_nested_set)\n\n\nAwesome Nested Set is an implementation of the nested set pattern for ActiveRecord models.\nIt is a replacement for acts_as_nested_set and BetterNestedSet, but more awesome.\n\nOlder versions: Version 3.2 supports Rails 6, 3.1 supports Rails 5 \u0026 4. Version 2 supports Rails 3. \nGem versions prior to 2.0 support Rails 2.\n\n## What makes this so awesome?\n\nThis 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.\n\n\n## Installation\n\nAdd to your Gemfile:\n\n```ruby\ngem 'awesome_nested_set'\n```\n\n## Usage\n\nTo make use of `awesome_nested_set` your model needs to have 3 fields:\n`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.\nYou can also have optional fields: `depth` and `children_count`. These fields are configurable.\nNote that the `children_count` column must have `null: false` and `default: 0` to\nfunction properly.\n\n```ruby\nclass CreateCategories \u003c ActiveRecord::Migration\n  def change\n    create_table :categories do |t|\n      t.string :name\n      t.integer :parent_id, null: true, index: true\n      t.integer :lft, null: false, index: true\n      t.integer :rgt, null: false, index: true\n\n      # optional fields\n      t.integer :depth, null: false, default: 0\n      t.integer :children_count, null: false, default: 0\n      t.timestamps\n    end\n  end\nend\n```\n\nEnable the nested set functionality by declaring `acts_as_nested_set` on your model\n\n```ruby\nclass Category \u003c ActiveRecord::Base\n  acts_as_nested_set\nend\n```\n\nRun `rake rdoc` to generate the API docs and see [CollectiveIdea::Acts::NestedSet](lib/awesome_nested_set/awesome_nested_set.rb) for more information.\n\n## Options\n\nYou can pass various options to `acts_as_nested_set` macro. Configuration options are:\n\n* `parent_column`: specifies the column name to use for keeping the position integer (default: parent_id)\n* `primary_column`: specifies the column name to use as the inverse of the parent column (default: id)\n* `left_column`: column name for left boundary data (default: lft)\n* `right_column`: column name for right boundary data (default: rgt)\n* `depth_column`: column name for the depth data default (default: depth)\n* `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 =\u003e [:notable_id, :notable_type]`\n* `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.\n* `counter_cache`: adds a counter cache for the number of children. defaults to false. Example: `acts_as_nested_set :counter_cache =\u003e :children_count`\n* `order_column`: on which column to do sorting, by default it is the left_column_name. Example: `acts_as_nested_set :order_column =\u003e :position`\n* `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)\n\nSee [CollectiveIdea::Acts::NestedSet::Model::ClassMethods](/lib/awesome_nested_set/model.rb#L26) for a list of class methods and [CollectiveIdea::Acts::NestedSet::Model](lib/awesome_nested_set/model.rb#L13) for a list of instance methods added to acts_as_nested_set models\n\n## Indexes\n\nIt 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`).\n\n## Callbacks\n\nThere are three callbacks called when moving a node:\n`before_move`, `after_move` and `around_move`.\n\n```ruby\nclass Category \u003c ActiveRecord::Base\n  acts_as_nested_set\n\n  after_move :rebuild_slug\n  around_move :da_fancy_things_around\n\n  private\n\n  def rebuild_slug\n    # do whatever\n  end\n\n  def da_fancy_things_around\n    # do something...\n    yield # actually moves\n    # do something else...\n  end\nend\n```\n\nBeside this there are also hooks to act on the newly added or removed children.\n\n```ruby\nclass Category \u003c ActiveRecord::Base\n  acts_as_nested_set  :before_add     =\u003e :do_before_add_stuff,\n                      :after_add      =\u003e :do_after_add_stuff,\n                      :before_remove  =\u003e :do_before_remove_stuff,\n                      :after_remove   =\u003e :do_after_remove_stuff\n\n  private\n\n  def do_before_add_stuff(child_node)\n    # do whatever with the child\n  end\n\n  def do_after_add_stuff(child_node)\n    # do whatever with the child\n  end\n\n  def do_before_remove_stuff(child_node)\n    # do whatever with the child\n  end\n\n  def do_after_remove_stuff(child_node)\n    # do whatever with the child\n  end\nend\n```\n\n## Protecting attributes from mass assignment (for Rails \u003c 4)\n\nIt's generally best to \"whitelist\" the attributes that can be used in mass assignment:\n\n```ruby\nclass Category \u003c ActiveRecord::Base\n  acts_as_nested_set\n  attr_accessible :name, :parent_id\nend\n```\n\nIf for some reason that is not possible, you will probably want to protect the `lft` and `rgt` attributes:\n\n```ruby\nclass Category \u003c ActiveRecord::Base\n  acts_as_nested_set\n  attr_protected :lft, :rgt\nend\n```\n\n\n## Add to your existing project\n\nTo make use of `awesome_nested_set`, your model needs to have 3 fields:\n`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.\nYou can also have optional fields, `depth` and `children_count`.\n\nCreate a migration to add fields:\n\n```ruby\nclass AddNestedToCategories \u003c ActiveRecord::Migration\n\n  def self.up\n    add_column :categories, :parent_id, :integer # Comment this line if your project already has this column\n    # Category.where(parent_id: 0).update_all(parent_id: nil) # Uncomment this line if your project already has :parent_id\n    add_column :categories, :lft,       :integer\n    add_column :categories, :rgt,       :integer\n\n    # optional fields\n    add_column :categories, :depth,          :integer\n    add_column :categories, :children_count, :integer\n\n    # This is necessary to update :lft and :rgt columns\n    Category.reset_column_information\n    Category.rebuild!\n  end\n\n  def self.down\n    remove_column :categories, :parent_id\n    remove_column :categories, :lft\n    remove_column :categories, :rgt\n\n    # optional fields\n    remove_column :categories, :depth\n    remove_column :categories, :children_count\n  end\n\nend\n```\n\nEnable the nested set functionality by declaring `acts_as_nested_set` on your model\n\n```ruby\nclass Category \u003c ActiveRecord::Base\n  acts_as_nested_set\nend\n```\n\nYour project is now ready to run with the `awesome_nested_set` gem!\n\n\n## Conversion from other trees\n\nComing from acts_as_tree or another system where you only have a parent_id? No problem. Simply add the lft \u0026 rgt fields as above, and then run:\n\n```ruby\nCategory.rebuild!\n```\n\nYour tree will be converted to a valid nested set. Awesome!\n\nNote: You can use `Category.rebuild!(false)` to skip model validations when performing the rebuild.\n\n## View Helper\n\nThe view helper is called #nested_set_options.\n\nExample usage:\n\n```erb\n\u003c%= f.select :parent_id, nested_set_options(Category, @category) {|i| \"#{'-' * i.level} #{i.name}\" } %\u003e\n\n\u003c%= select_tag 'parent_id', options_for_select(nested_set_options(Category) {|i| \"#{'-' * i.level} #{i.name}\" } ) %\u003e\n```\n\nSee [CollectiveIdea::Acts::NestedSet::Helper](lib/awesome_nested_set/helper.rb) for more information about the helpers.\n\n## How to contribute\n\nPlease see the ['Contributing' document](CONTRIBUTING.md).\n\nCopyright © 2008–2015 [Collective Idea](http://collectiveidea.com), released under the MIT license.\n","funding_links":["https://github.com/sponsors/parndt"],"categories":["Active Record Plugins","Ruby","ORM/ODM Extensions","Gems"],"sub_categories":["Active Record Nesting","Attributes Management"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcollectiveidea%2Fawesome_nested_set","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcollectiveidea%2Fawesome_nested_set","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcollectiveidea%2Fawesome_nested_set/lists"}