Problem
The transfer is raw SQL, so AR callbacks don't fire. Users inadvertently ship code that silently skips:
- Elasticsearch / OpenSearch / Algolia indexers
- Counter cache increments
- Russian-doll cache invalidation
touch: true associations
Each user rediscovers this the hard way.
Proposal
- Dedicated README section: "Callbacks are bypassed — what you need to handle yourself"
- Helper module
StagingTable::Callbacks that can reindex/invalidate in bulk:
StagingTable.stage(User,
after_transfer: ->(session, result) {
User.where(id: result.inserted_ids + result.updated_ids)
.find_in_batches { |batch| SearchIndexer.index_bulk(batch) }
}
) { |s| s.insert(rows) }
- Pairs with
returning: so users have IDs to work with
- Document the counter-cache recalculation pattern
Acceptance criteria
- README section with the four classes of bypass + a recipe for each
- Optional helper module (
StagingTable::Callbacks.reset_counters, etc.)
- Sample app / guide updated to include at least one of these
Problem
The transfer is raw SQL, so AR callbacks don't fire. Users inadvertently ship code that silently skips:
touch: trueassociationsEach user rediscovers this the hard way.
Proposal
StagingTable::Callbacksthat can reindex/invalidate in bulk:returning:so users have IDs to work withAcceptance criteria
StagingTable::Callbacks.reset_counters, etc.)