Class: ProjectUnification::TaxonNameHandler
- Inherits:
-
Object
- Object
- ProjectUnification::TaxonNameHandler
- Defined in:
- lib/project_unification/taxon_name_handler.rb
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#source_project_id ⇒ Object
readonly
Returns the value of attribute source_project_id.
-
#target_project_id ⇒ Object
readonly
Returns the value of attribute target_project_id.
Instance Method Summary collapse
-
#count_descendants(source_root) ⇒ Object
private
Count all descendants of source root (excluding root itself).
-
#determine_target_parent(target_project) ⇒ Object
private
Determine where to attach the source hierarchy in the target project.
-
#disable_cached_callbacks ⇒ Object
private
Temporarily disable cached field callbacks for performance.
-
#initialize(source_project_id:, target_project_id:, options: {}) ⇒ TaxonNameHandler
constructor
A new instance of TaxonNameHandler.
-
#migrate ⇒ Hash
Migrate TaxonName hierarchy from source to target project.
-
#move_children_to_target(source_root, target_parent) ⇒ Object
private
Move all direct children of source root to target parent Updates both parent_id AND project_id atomically.
-
#update_all_descendants_project_id(source_root) ⇒ Object
private
Update project_id for all descendants in one bulk operation.
Constructor Details
#initialize(source_project_id:, target_project_id:, options: {}) ⇒ TaxonNameHandler
Returns a new instance of TaxonNameHandler.
13 14 15 16 17 |
# File 'lib/project_unification/taxon_name_handler.rb', line 13 def initialize(source_project_id:, target_project_id:, options: {}) @source_project_id = source_project_id @target_project_id = target_project_id @options = end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
11 12 13 |
# File 'lib/project_unification/taxon_name_handler.rb', line 11 def @options end |
#source_project_id ⇒ Object (readonly)
Returns the value of attribute source_project_id.
11 12 13 |
# File 'lib/project_unification/taxon_name_handler.rb', line 11 def source_project_id @source_project_id end |
#target_project_id ⇒ Object (readonly)
Returns the value of attribute target_project_id.
11 12 13 |
# File 'lib/project_unification/taxon_name_handler.rb', line 11 def target_project_id @target_project_id end |
Instance Method Details
#count_descendants(source_root) ⇒ Object (private)
Count all descendants of source root (excluding root itself)
88 89 90 |
# File 'lib/project_unification/taxon_name_handler.rb', line 88 def count_descendants(source_root) source_root.descendants.unscope(:order).count end |
#determine_target_parent(target_project) ⇒ Object (private)
Determine where to attach the source hierarchy in the target project
79 80 81 82 83 84 85 |
# File 'lib/project_unification/taxon_name_handler.rb', line 79 def determine_target_parent(target_project) if [:root_taxon_name_id] TaxonName.find([:root_taxon_name_id]) else target_project.root_taxon_name end end |
#disable_cached_callbacks ⇒ Object (private)
Temporarily disable cached field callbacks for performance
118 119 120 121 122 123 |
# File 'lib/project_unification/taxon_name_handler.rb', line 118 def disable_cached_callbacks TaxonName.no_cached_thread = true yield ensure TaxonName.no_cached_thread = nil end |
#migrate ⇒ Hash
Migrate TaxonName hierarchy from source to target project
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/project_unification/taxon_name_handler.rb', line 21 def migrate source_project = Project.find(source_project_id) target_project = Project.find(target_project_id) source_root = source_project.root_taxon_name target_parent = determine_target_parent(target_project) stats = { track: :special, model: 'TaxonName', migrated: 0, source_root_id: source_root.id, target_parent_id: target_parent.id, closure_tree_rebuilt: false, errors: [] } begin # Count all descendants before moving (excluding root) total_count = count_descendants(source_root) # Skip if there are no children to migrate (only root exists) if total_count == 0 stats[:migrated] = 0 stats[:note] = 'No TaxonNames to migrate (only root exists)' return stats end # Temporarily disable cached field updates for performance disable_cached_callbacks do move_children_to_target(source_root, target_parent) update_all_descendants_project_id(source_root) stats[:migrated] = total_count # Rebuild only target_parent's subtree — all source names now hang off it. # TaxonName.rebuild! is O(all projects); instance rebuild! is O(moved subtree). # # Ancestors of target_parent are correctly handled: closure_tree's instance # rebuild! seeds each node's ancestor entries by copying rows where # descendant_id = parent_id, which already includes all ancestors above # target_parent. No separate rebuild of those nodes is needed. target_parent.rebuild! stats[:closure_tree_rebuilt] = true end rescue => e stats[:errors] << { error: e., backtrace: e.backtrace.first(3) } end stats end |
#move_children_to_target(source_root, target_parent) ⇒ Object (private)
Move all direct children of source root to target parent Updates both parent_id AND project_id atomically
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/project_unification/taxon_name_handler.rb', line 94 def move_children_to_target(source_root, target_parent) children = source_root.children.unscope(:order) children.each do |child| child.update_columns( parent_id: target_parent.id, project_id: target_project_id ) end end |
#update_all_descendants_project_id(source_root) ⇒ Object (private)
Update project_id for all descendants in one bulk operation
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/project_unification/taxon_name_handler.rb', line 106 def update_all_descendants_project_id(source_root) # Get all descendants except direct children (already updated in move_children_to_target) # Use closure_tree's descendants method with unscope for performance descendants = source_root.descendants.unscope(:order).where.not(parent_id: source_root.id) return if descendants.empty? # Bulk update all descendants' project_id via ActiveRecord for performance TaxonName.where(id: descendants.select(:id)).update_all(project_id: target_project_id) end |