Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time



  • Ruby 2.7 support
  • Ordering raw SQL argument wrapped with Arel.sql


Closure Tree is now tested against Rails 6.0

  • Directly require core_ext for String#strip_heredocPR 350
  • Call Module#module_parent instead of deprecated #parentPR 354


Closure Tree is now tested against Rails 5.2

  • Postpone configuration (database introspection)PR 264
  • Fix "tree.find_by_path([])" PR 288
  • Fixed generator specs and added migration version PR 292
  • Eliminate deprecation warnings in ActiveRecord 5.2 PR 296
  • When using 'oracle_enhanced', remove 'AS' on the table_name alias. PR 298
  • README update PR 301
  • Add with_descendant finder PR 302
  • Fix pg version for rails prior 5.1 PR 303
  • Test on Rails 5.2 & fix mysql for older Rails PR 304
  • Test with ActiveRecord 5.2.0 PR 307
  • README update PR 310
  • FactoryBot linter failing for a model that uses closure_tree PR 311
  • Added dont_order_roots option PR 312
  • Added instance methods to determine the relationship between 2 nodes PR 314
  • Add an instance method to check the relationship between 2 nodes: #family_of? PR 319
  • Remove options restrictions on has_closure_tree_root PR 321
  • Fix uninitialized variable warnings PR 323


Closure Tree is now tested against Rails 5.1, and just passed 50 contributors and 1000 stars on github! 🎉!

Note that Closure Tree has moved to a new "Closure Tree" github organization. Future gem releases will be done by other contributors.



  • Merged PR 236 which adds documentation for has_closure_tree_root.
  • Added ruby 2.4 and dropped Rails 4.1 from the build matrix.




  • Added official support for ActiveRecord 5.0! Thanks to Abdelkader Boudih, Jay Fredlund, Veselin Stoyanov, and Aaron Russell for all the PRs.
  • Add database_less configuration to not raise an error during build step when database is unavailable which is a common case in some PaaS like (Heroku, Catalyze, ..., etc).


  • Andrew Kumanyaev dramatically improved mutation performance on large trees. Thanks for the PR!
  • Martin Schmidt discovered and fixed build problems due to new versions of mysql2 and ammeter which broke Travis builds. Thanks for the PR!
  • Fabien MICHEL updated the README with another example. Thanks for the PR!


  • Dropped support for versions of Rails 3.2 and 4.0 (which are no longer supported).
  • Dropped support for Ruby 1.9 and JRuby 1.9 (which are no longer supported).
  • Added support for .hash_tree from .parent and .children. Addresses PR146. Thanks for reporting this and the breaking test, Mike!


  • Eduardo Turiño renamed acts_as_tree to has_closure_tree. We'll keep both annotations around for the forseeable future, but I think not name-colliding by default is strictly better. (Thanks for both the suggestion and PR!)
  • Ryan Selk made several enhancements to the migration generation (thanks!).
  • ruok5 updated the README to clarify a heirarchy maintenance usecase. Thanks!
  • Made migrations error with a helpful message if the target didn't have the has_closure_tree or acts_as_tree annotation. This addresses issue 131.


  • Fixed bug in rails g closure_tree:migration (introduced by me, not by seuros!) that was reported and fixed by Rich Kuo. Thanks!



Breaking API changes

  • find_by_path and find_or_create_by_path now takes either an array of strings or an array of attribute hashes, which can include the inheritance column for STI support.
  • Removed the extraneous base_class acts_as_tree option—it needlessly duplicated ActiveRecord's method.
  • Removed the unused name acts_as_tree option.

Improvements and bugfixes

  • Cleaned up the inheritance support methods to delegate correctly to ActiveRecord
  • Fixed a query generation error when ancestor paths exceeded 50 items.
  • Documented the .touch option



  • Pulled in 106 which fixed a bug introduced in 4.6.0 which broke if the numeric ordering column wasn't named 'sort_order'. Tests have been added. Thanks for the fix, Fission Xuiptz!



  • Deterministically ordered trees are guaranteed to have a sort_order now.

    This may be a breaking change if you're expecting sort_order to be nullable.

    Many thanks to David Schmidt for raising and working on the issue!

  • Added append_child and prepend_child

  • All raw SQL is now strip_heredoc'ed



  • Added .self_and_descendant_ids and .self_and_ancestors_ids from PR92. Thanks, Kir Shatrov!

  • Dropped support for Rails 3.0.


  • Use foreigner to prove that things are inserted and deleted without violating foreign key constraints

  • Added Rails 4.1.0.rc2 as a Travis CI build target


  • Support for Heroku's cray assets:precompile hack for Rails 4. Addresses issue 78. Thanks for the assist, Alex Bowman.


  • More massaging for Rails 4 and attr_accessible support


  • self_and_ancestors and ancestry_hierarchy are reloaded when nodes are reparented. Addresses issue 68. Thanks for the assist, Ivan Stana.


  • Explicitly added MIT licensing to the gemspec.


  • Fix for potential deadlock from delete_hierarchy_references not being called within an advisory lock. Thanks, Armando Guereca, for finding that!

  • Sped up find_or_create_by_path to skip cycle detection validation. A node whose ancestry was 200-deep took 20 seconds to create (!!), and now takes < 1 second.

  • Fixed issue with MySQL that prevented nodes > 60 levels deep from being created


  • Support for root?, child?, and proper parent-child associations when both the parent and the child are not persisted. Addresses issue 64. Thanks for the help, Gabriel Mazetto!


  • Fixed attr_accessible? error introduced in 4.2.2 (issue 66).
  • Switched to use new WithAdvisoryLock::DatabaseAdapterSupport (in v0.0.9) to add Postgis support


  • Support attr_accessible and strong_attributes even if you're on Rails 4


  • Deleting from NumericDeterministicOrdering doesn't create sort order gaps anymore.


  • Added with_ancestor(*ancestors). Thanks for the idea, Matt!
  • Applied Leonel Galan's fix for Strong Attribute support
  • find_or_create_by now uses passed-in attributes as both selection and creation criteria. Thanks for the help, Judd Blair! Please note that this changes prior behavior—test your code with this new version!
  • ct_advisory_lock was moved into the _ct support class, to reduce model method pollution
  • Moved a bunch of code into more focused piles of module mixins


  • Added support for Rails 4.0.0.rc1 and Ruby 2.0.0 (while maintaining backward compatibility with Rails 3, BOOYA)
  • Added #to_dot_digraph, suitable for Graphviz rendering


  • Numeric, deterministically ordered siblings will always be [0..#{self_and_siblings.count}] (previously, the sort order might use negative values, which broke the preordering). Resolves issue 49. Thanks for the help, Leonel Galan, Juan Hoyos, and Michael Elfassy!

  • The order option can be a symbol now. Resolves issue 46.


  • Moved all of closure_tree's implementation-detail methods into a ClosureTree::Support instance, which removes almost all of the namespace pollution in your models that wasn't for normal consumption. If you were using any of these methods, they're now available through the "_ct" class and instance member.

    This change may break consumers, so I incremented the major version number, even though no new functionality was released.


  • Prevent faulty SQL statement when #siblings is called on an unsaved records. Resolves issue 52. Perfect pull request by Gary Greyling.

  • The .roots class method now correctly respects the :order option. Resolves issue 53. Thanks for finding this, Brendon Muir!


  • Multipart constant names like "Admin::PageHierarchy" are now supported. Resolves issue 47. Thanks for the perfect pull request, Simon Menke!

  • Committing transactions involving large numbers of hierarchy model classes was very slow due to hash collisions in the hierarchy class. A better hash implementation addressed issue 48. Thanks, Joel Turkel!


  • Added #roots_and_descendants_preordered. Thanks for the suggestion, Leonel Galan!


  • Added .child_ids.
  • Removed dependent => destroy on the descendant_hierarchy and ancestor_hierarchy collections (they were a mistake).
  • Clarified documentation for creation and child associations. Because Tag.create!(:parent => ...) requires a .reload, I removed it as an example.

All three of these improvements were suggested by Andrew Bromwich. Thanks!


  • find_by_path uses 1 SELECT now. BOOM.


  • Double-check locking for find_or_create_by_path


  • Support for preordered descendants. This requires a numeric sort order column. Resolves feature request 38.
  • Moved modules from acts_as_tree into separate files


Due to MySQL's inability to lock rows properly, I've switched to advisory_locks for all write paths. This will prevent deadlocks, addressing issue 41.


  • Support for UUID primary keys. Addresses issue 40. Thanks for the pull request, Julien!


  • Moved requires into ActiveSupport.on_load
  • Added require 'with_advisory_lock'


Thread safety!

  • Advisory locks were integrated with the class-level find_or_create_by_path and rebuild!.
  • Pessimistic locking is used by the instance-level find_or_create_by_path.


  • Don Morrison massaged the #hash_tree query to be more efficient, and found a bug in hash_tree's query that resulted in duplicate rows, wasting time on the ruby side.


  • Added workaround for ActiveRecord::Observer usage pre-db-creation. Addresses issue 32. Thanks, Don Morrison!






  • Fixed issue 23, which added support for #siblings when sort_order wasn't specified. Thanks, Gary Greyling!


  • Fixed issue 20, which affected deterministic ordering when siblings where different STI classes. Thanks, edwinramirez!


Added support for:

  • :hierarchy_class_name as an option
  • ActiveRecord::Base.table_name_prefix
  • ActiveRecord::Base.table_name_suffix

This addresses issue 21. Thanks, Judd Blair!



  • Fixed issue 18, which affected append_node/prepend_node ordering when the first node didn't have an explicit order_by value


  • Reverted .gemspec mistake that changed add_development_dependency to add_runtime_dependency


Fixed issue 15:

  • "parent" is now attr_accessible, which adds support for constructor-provided parents.
  • updated readme accordingly


  • Merged calebphillips' patch for a more efficient leaves query


  • Added support for partially-unsaved hierarchies issue 13:
a = "a")
b = "b")
a.children << b



  • Added ancestor_ids, descendant_ids, and sibling_ids
  • Added example spec to solve issue 9


  • Added support for deterministic ordering of nodes.


  • Switched to using has_many :though rather than has_and_belongs_to_many



  • Added support for ActiveRecord's whitelist_attributes (Make sure you read the Rails Security Guide, and enable config.active_record.whitelist_attributes in your config/application.rb ASAP!)


  • Fix for ancestry-loop detection (performed by a validation, not through raising an exception in before_save)


  • Support 3.2.0's fickle deprecation of InstanceMethods (Thanks, jheiss)!


  • Support for polymorphic trees
  • find_by_path and find_or_create_by_path signatures changed to support constructor attributes
  • tested against Rails 3.1.3


  • Had to increment the major version, as rebuild! will need to be called by prior consumers to support the new leaves class and instance methods.
  • Tag deletion is supported now along with :dependent => :destroy and :dependent => :delete_all
  • Switched from default rails plugin directory structure to rspec
  • Support for running specs under different database engines: export DB ; for DB in sqlite3 mysql postgresql ; do rake ; done