Class: ProjectUnification::SpecialHandlers::DocumentHandler

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

Overview

Handler for Document with fingerprint-based deduplication. Mirrors ImageHandler — see its comment for the Phase 1 / Phase 2 design.

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: {}) ⇒ DocumentHandler

Returns a new instance of DocumentHandler.



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

Returns [[source_document, target_id], ...] for documents whose fingerprint matches one in the target project. Excludes .prj/.cpg files since fingerprint uniqueness is not enforced for those.



389
390
391
392
393
394
395
396
397
# File 'lib/project_unification/special_handlers.rb', line 389

def duplicate_pairs
  target_by_fingerprint = non_shapefile_documents(target_project_id)
                            .pluck(:document_file_fingerprint, :id)
                            .to_h

  non_shapefile_documents(source_project_id)
    .where(document_file_fingerprint: target_by_fingerprint.keys)
    .map { |doc| [doc, target_by_fingerprint[doc.document_file_fingerprint]] }
end

#migrate ⇒ Object



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: 'Document',
    migrated: 0,
    duplicates_found: [],
    errors: [],
    merge_registry: []
  }

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

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

#non_shapefile_documents(project_id) ⇒ Object (private)



399
400
401
402
403
# File 'lib/project_unification/special_handlers.rb', line 399

def non_shapefile_documents(project_id)
  Document.where(project_id: project_id)
          .where.not(document_file_fingerprint: nil)
          .where.not("document_file_file_name ILIKE '%.prj' OR document_file_file_name ILIKE '%.cpg'")
end