Class: ProjectUnification::SpecialHandlers::ImageHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/project_unification/special_handlers.rb

Overview

Handler for Image with fingerprint-based deduplication.

Phase 1 (migrate): source images whose fingerprint collides with a target image have their fingerprint replaced with a per-record sentinel string so the bulk SQL update can move them without a uniqueness conflict. They are registered in merge_registry for Phase 2.

Phase 2: handled by the generic Service#run_cleanup, which calls target.unify(sentinel) to re-route all associations and destroy the sentinel.

Constant Summary collapse

SENTINEL_PREFIX =
'UNIFICATION TO PROJECT'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_project_id:, target_project_id:, options: {}) ⇒ ImageHandler

Returns a new instance of ImageHandler.



340
341
342
343
# File 'lib/project_unification/special_handlers.rb', line 340

def initialize(source_project_id:, target_project_id:, options: {})
  @source_project_id = source_project_id
  @target_project_id = target_project_id
end

Instance Attribute Details

#source_project_idObject (readonly)

Returns the value of attribute source_project_id.



338
339
340
# File 'lib/project_unification/special_handlers.rb', line 338

def source_project_id
  @source_project_id
end

#target_project_idObject (readonly)

Returns the value of attribute target_project_id.



338
339
340
# File 'lib/project_unification/special_handlers.rb', line 338

def target_project_id
  @target_project_id
end

Instance Method Details

#duplicate_pairsObject (private)



386
387
388
389
390
391
392
393
394
395
# File 'lib/project_unification/special_handlers.rb', line 386

def duplicate_pairs
  target_by_fingerprint = Image.where(project_id: target_project_id)
                               .where.not(image_file_fingerprint: nil)
                               .pluck(:image_file_fingerprint, :id)
                               .to_h

  Image.where(project_id: source_project_id)
       .where(image_file_fingerprint: target_by_fingerprint.keys)
       .map { |img| [img, target_by_fingerprint[img.image_file_fingerprint]] }
end

#migrateObject



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/project_unification/special_handlers.rb', line 345

def migrate
  result = {
    track: :special,
    model: 'Image',
    migrated: 0,
    duplicates_found: [],
    errors: [],
    merge_registry: []
  }

  duplicate_pairs.each do |source_image, target_id|
    original_fingerprint = source_image.image_file_fingerprint
    source_image.update_columns(
      image_file_fingerprint: "#{SENTINEL_PREFIX} #{target_project_id} #{source_image.id}"
    )
    result[:duplicates_found] << {
      source_id: source_image.id,
      target_id: target_id,
      fingerprint: original_fingerprint
    }
    result[:merge_registry] << {
      model: 'Image',
      renamed_id: source_image.id,
      target_id: target_id
    }
  end

  result[:migrated] = Image.where(project_id: source_project_id)
                           .update_all(project_id: target_project_id)
  result
rescue => e
  {
    track: :special,
    model: 'Image',
    migrated: 0,
    errors: [{ error: e.message, backtrace: e.backtrace.first(3) }]
  }
end