@@ -46,6 +46,7 @@ for a description of different tree storage algorithms.
4646-  [ Polymorphic hierarchies with STI] ( #polymorphic-hierarchies-with-sti ) 
4747-  [ Deterministic ordering] ( #deterministic-ordering ) 
4848-  [ Concurrency] ( #concurrency ) 
49+ -  [ Multi-Database Support] ( #multi-database-support ) 
4950-  [ FAQ] ( #faq ) 
5051-  [ Testing] ( #testing ) 
5152-  [ Change log] ( #change-log ) 
@@ -61,11 +62,11 @@ Note that closure_tree only supports ActiveRecord 7.2 and later, and has test co
61623 .   Add ` has_closure_tree `  (or ` acts_as_tree ` , which is an alias of the same method) to your hierarchical model:
6263
6364    ``` ruby 
64-     class  Tag  < ActiveRecord :: Base 
65+     class  Tag  < ApplicationRecord 
6566      has_closure_tree
6667    end 
6768
68-     class  AnotherTag  < ActiveRecord :: Base 
69+     class  AnotherTag  < ApplicationRecord 
6970      acts_as_tree
7071    end 
7172    ```
@@ -82,7 +83,7 @@ Note that closure_tree only supports ActiveRecord 7.2 and later, and has test co
8283    You may want to also [add a column for deterministic ordering of children](#deterministic-ordering), but that'  s optional.
8384
8485    ` ` ` ruby
85-     class AddParentIdToTag < ActiveRecord::Migration 
86+     class AddParentIdToTag < ActiveRecord::Migration[7.2]  
8687      def change 
8788        add_column :tags, :parent_id, :integer 
8889      end 
@@ -384,7 +385,7 @@ Polymorphic models using single table inheritance (STI) are supported:
3843852. Subclass the model class. You only need to add ```has_closure_tree``` to your base class: 
385386
386387```ruby 
387- class Tag < ActiveRecord::Base  
388+ class Tag < ApplicationRecord  
388389  has_closure_tree 
389390end 
390391class WhenTag < Tag ; end 
@@ -411,7 +412,7 @@ By default, children will be ordered by your database engine, which may not be w
411412If you want to order children alphabetically, and your model has a ```name``` column, you'  d do  this: 
412413
413414` ` ` ruby
414- class Tag < ActiveRecord::Base  
415+ class Tag < ApplicationRecord  
415416  has_closure_tree order: 'name' 
416417end 
417418` ` ` 
@@ -425,7 +426,7 @@ t.integer :sort_order
425426and  in  your model: 
426427
427428` ` ` ruby
428- class OrderedTag < ActiveRecord::Base  
429+ class OrderedTag < ApplicationRecord  
429430  has_closure_tree order: 'sort_order', numeric_order: true 
430431end 
431432` ` ` 
@@ -525,14 +526,106 @@ If you are already managing concurrency elsewhere in your application, and want
525526of with_advisory_lock, pass ` ` ` with_advisory_lock: false` ` `   in  the options hash: 
526527
527528` ` ` ruby
528- class Tag 
529+ class Tag < ApplicationRecord  
529530  has_closure_tree with_advisory_lock: false 
530531end 
531532` ` ` 
532533
533534Note  that you * will eventually have data corruption*  if  you disable advisory locks, write to your
534535database with multiple threads, and  don' t provide an alternative mutex.
535536
537+ ### Customizing Advisory Lock Names 
538+ 
539+ By default, closure_tree generates advisory lock names based on the model class name. You can customize 
540+ this behavior in several ways: 
541+ 
542+ ```ruby 
543+ # Static string 
544+ class Tag < ApplicationRecord 
545+   has_closure_tree advisory_lock_name: '  custom_tag_lock' 
546+ end 
547+ 
548+ # Dynamic via Proc 
549+ class Tag < ApplicationRecord 
550+   has_closure_tree advisory_lock_name: ->(model_class) { "#{Rails.env}_#{model_class.name.underscore}" } 
551+ end 
552+ 
553+ # Delegate to model method 
554+ class Tag < ApplicationRecord 
555+   has_closure_tree advisory_lock_name: :custom_lock_name 
556+    
557+   def self.custom_lock_name 
558+     "tag_lock_#{current_tenant_id}" 
559+   end 
560+ end 
561+ ``` 
562+ 
563+ This is particularly useful when: 
564+ * You need environment-specific lock names 
565+ * You'  re using  multi- tenancy and  need tenant- specific locks
566+ *  You  want to avoid lock name collisions between similar model names
567+ 
568+ # # Multi-Database Support
569+ 
570+ Closure  Tree  fully supports running with multiple databases simultaneously, including mixing different database engines (PostgreSQL , MySQL , SQLite ) in  the same application. This  is particularly useful for: 
571+ 
572+ *  Applications  with read replicas
573+ *  Sharding  strategies
574+ *  Testing  with different database engines
575+ *  Gradual  database migrations
576+ 
577+ # ## Database-Specific Behaviors
578+ 
579+ # ### PostgreSQL
580+ *  Full  support for  advisory locks via ` with_advisory_lock` 
581+ *  Excellent  concurrency support with row- level locking
582+ *  Best  overall performance for  tree operations
583+ 
584+ # ### MySQL
585+ *  Advisory  locks supported via ` with_advisory_lock` 
586+ *  Note:  MySQL ' s row-level locking may incorrectly report deadlocks in some cases
587+ * Requires MySQL 5.7.12+ to avoid hierarchy maintenance errors 
588+ 
589+ #### SQLite 
590+ * **No advisory lock support** - always returns false from `with_advisory_lock` 
591+ * Falls back to file-based locking for tests 
592+ * Suitable for development and testing, but not recommended for production with concurrent writes 
593+ 
594+ ### Configuration 
595+ 
596+ When using multiple databases, closure_tree automatically detects the correct adapter for each connection: 
597+ 
598+ ```ruby 
599+ class Tag < ApplicationRecord 
600+   connects_to database: { writing: :primary, reading: :replica } 
601+   has_closure_tree 
602+ end 
603+ 
604+ class Category < ApplicationRecord   
605+   connects_to database: { writing: :sqlite_db } 
606+   has_closure_tree 
607+ end 
608+ ``` 
609+ 
610+ Each model will use the appropriate database-specific SQL syntax and features based on its connection adapter. 
611+ 
612+ ### Testing with Multiple Databases 
613+ 
614+ You can run the test suite against different databases: 
615+ 
616+ ```bash 
617+ # Run with PostgreSQL 
618+ DATABASE_URL=postgres://localhost/closure_tree_test rake test 
619+ 
620+ # Run with MySQL   
621+ DATABASE_URL=mysql2://localhost/closure_tree_test rake test 
622+ 
623+ # Run with SQLite (default) 
624+ rake test 
625+ ``` 
626+ 
627+ For simultaneous multi-database testing, the test suite automatically sets up connections to all three database types when available. 
628+ 
536629## I18n 
537630
538631You can customize error messages using [I18n](http://guides.rubyonrails.org/i18n.html): 
0 commit comments