Module: Models::ItemLtreeSync

Extended by:
ActiveSupport::Concern
Included in:
Item
Defined in:
app/concerns/models/item_ltree_sync.rb

Overview

Models::ItemLtreeSync - Manual sync methods for ltree paths on items

AUTOMATIC SYNC IS HANDLED BY DATABASE TRIGGERS (see db/triggers/):

  • sync_item_ltree_paths: BEFORE INSERT/UPDATE on items
  • sync_item_all_pl_paths: AFTER INSERT/UPDATE/DELETE on item_product_lines
  • cascade_pl_path_to_items: AFTER UPDATE on product_lines.ltree_path_ids
  • cascade_pc_path_to_items: AFTER UPDATE on product_categories.ltree_path_ids

This concern provides:

  • Manual sync methods for data repair/backfill
  • Bulk sync utilities for maintenance tasks

Columns managed (by triggers):

  • primary_pl_path_ids: ltree path from primary_product_line_id
  • all_pl_paths_ids: array of ltree paths from ALL product lines (constellation)
  • pc_path_ids: ltree path from product_category_id

Usage:

Manual sync (for data repair)

item.sync_ltree_paths!

Bulk sync (for maintenance)

Item.bulk_sync_ltree_paths!(item_ids)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#skip_ltree_syncObject

Skip syncing during mass updates (backfill, etc.)
Note: This only affects manual sync_ltree_paths! calls, not DB triggers



35
36
37
# File 'app/concerns/models/item_ltree_sync.rb', line 35

def skip_ltree_sync
  @skip_ltree_sync
end

Class Method Details

.bulk_sync_ltree_paths!(item_ids) ⇒ Object

Bulk sync ltree paths for multiple items (efficient for worker)
Uses batch updates to minimize queries



41
42
43
44
45
46
47
48
# File 'app/concerns/models/item_ltree_sync.rb', line 41

def bulk_sync_ltree_paths!(item_ids)
  return if item_ids.blank?

  # Process in batches to avoid memory issues
  where(id: item_ids).find_each(batch_size: 500) do |item|
    item.sync_ltree_paths!
  end
end

.sync_items_for_product_categories!(category_ids) ⇒ Object

Sync all items associated with given product category IDs



69
70
71
72
73
74
# File 'app/concerns/models/item_ltree_sync.rb', line 69

def sync_items_for_product_categories!(category_ids)
  return if category_ids.blank?

  item_ids = where(product_category_id: category_ids).pluck(:id)
  bulk_sync_ltree_paths!(item_ids)
end

.sync_items_for_product_lines!(product_line_ids) ⇒ Object

Sync all items associated with given product line IDs
Called when product line paths change



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'app/concerns/models/item_ltree_sync.rb', line 52

def sync_items_for_product_lines!(product_line_ids)
  return if product_line_ids.blank?

  # Find items with these product lines (primary or constellation)
  item_ids = joins(:item_product_lines)
             .where(item_product_lines: { product_line_id: product_line_ids })
             .distinct
             .pluck(:id)

  # Also include items with primary_product_line_id
  item_ids += where(primary_product_line_id: product_line_ids).pluck(:id)
  item_ids.uniq!

  bulk_sync_ltree_paths!(item_ids)
end

Instance Method Details

#build_ltree_paths_from_associationsObject

Build paths (called by callback or sync method)



94
95
96
97
98
# File 'app/concerns/models/item_ltree_sync.rb', line 94

def build_ltree_paths_from_associations
  build_primary_pl_paths
  build_all_pl_paths
  build_pc_paths
end

#sync_ltree_paths!Object

Sync this item's ltree paths from its associations



78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'app/concerns/models/item_ltree_sync.rb', line 78

def sync_ltree_paths!
  return if skip_ltree_sync

  build_ltree_paths_from_associations

  # Use update_columns to skip callbacks and avoid loops
  updates = {
    primary_pl_path_ids: primary_pl_path_ids,
    all_pl_paths_ids: all_pl_paths_ids,
    pc_path_ids: pc_path_ids
  }

  update_columns(updates)
end