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.



275
276
277
278
# File 'lib/project_unification/special_handlers.rb', line 275

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_id ⇒ Object (readonly)

Returns the value of attribute source_project_id.



273
274
275
# File 'lib/project_unification/special_handlers.rb', line 273

def source_project_id
  @source_project_id
end

#target_project_id ⇒ Object (readonly)

Returns the value of attribute target_project_id.



273
274
275
# File 'lib/project_unification/special_handlers.rb', line 273

def target_project_id
  @target_project_id
end

Instance Method Details

#duplicate_pairs ⇒ Object (private)



321
322
323
324
325
326
327
328
329
330
# File 'lib/project_unification/special_handlers.rb', line 321

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

#migrate ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/project_unification/special_handlers.rb', line 280

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