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.)
This only affects manual sync_ltree_paths! calls, not DB triggers



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

def skip_ltree_sync
  @skip_ltree_sync
end

Class Method Details

.bulk_sync_ltree_paths!(item_ids) ⇒ void

This method returns an undefined value.

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

Parameters:

  • item_ids (Array<Integer>)

    IDs of the items to resync



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

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, &:sync_ltree_paths!)
end

.sync_items_for_product_categories!(category_ids) ⇒ void

This method returns an undefined value.

Sync all items associated with given product category IDs

Parameters:

  • category_ids (Array<Integer>)

    IDs of the product categories whose paths changed



75
76
77
78
79
80
# File 'app/concerns/models/item_ltree_sync.rb', line 75

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

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

.sync_items_for_product_lines!(product_line_ids) ⇒ void

This method returns an undefined value.

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

Parameters:

  • product_line_ids (Array<Integer>)

    IDs of the product lines whose paths changed



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

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
             .ids

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

  bulk_sync_ltree_paths!(item_ids)
end

Instance Method Details

#build_ltree_paths_from_associationsvoid

This method returns an undefined value.

Build paths (called by callback or sync method)

Populates +primary_pl_path_ids+, +all_pl_paths_ids+, and
+pc_path_ids+ in memory without persisting them.



110
111
112
113
114
# File 'app/concerns/models/item_ltree_sync.rb', line 110

def build_ltree_paths_from_associations
  build_primary_pl_paths
  build_all_pl_paths
  build_pc_paths
end

#sync_ltree_paths!Boolean?

Sync this item's ltree paths from its associations

Skipped when +skip_ltree_sync+ is set (mass updates/backfills). Uses
+update_columns+ to bypass callbacks and avoid sync loops.

Returns:

  • (Boolean, nil)

    result of +update_columns+, or nil when skipped



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'app/concerns/models/item_ltree_sync.rb', line 89

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