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.



293
294
295
296
# File 'lib/project_unification/special_handlers.rb', line 293

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.



291
292
293
# File 'lib/project_unification/special_handlers.rb', line 291

def source_project_id
  @source_project_id
end

#target_project_idObject (readonly)

Returns the value of attribute target_project_id.



291
292
293
# File 'lib/project_unification/special_handlers.rb', line 291

def target_project_id
  @target_project_id
end

Instance Method Details

#duplicate_pairsObject (private)



339
340
341
342
343
344
345
346
347
348
# File 'lib/project_unification/special_handlers.rb', line 339

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



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/project_unification/special_handlers.rb', line 298

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