Class: ActiveRecordGraphExtractor::Extractor

Inherits:
Object
  • Object
show all
Defined in:
lib/activerecord_graph_extractor/extractor.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = ActiveRecordGraphExtractor.configuration) ⇒ Extractor

Returns a new instance of Extractor.



10
11
12
13
# File 'lib/activerecord_graph_extractor/extractor.rb', line 10

def initialize(config = ActiveRecordGraphExtractor.configuration)
  @config = config
  @relationship_analyzer = RelationshipAnalyzer.new(config)
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



8
9
10
# File 'lib/activerecord_graph_extractor/extractor.rb', line 8

def config
  @config
end

#relationship_analyzerObject (readonly)

Returns the value of attribute relationship_analyzer.



8
9
10
# File 'lib/activerecord_graph_extractor/extractor.rb', line 8

def relationship_analyzer
  @relationship_analyzer
end

Instance Method Details

#dry_run(root_objects, options = {}) ⇒ Object



99
100
101
102
# File 'lib/activerecord_graph_extractor/extractor.rb', line 99

def dry_run(root_objects, options = {})
  analyzer = DryRunAnalyzer.new(config)
  analyzer.analyze(root_objects, options)
end

#extract(root_objects, options = {}) ⇒ Object

Raises:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/activerecord_graph_extractor/extractor.rb', line 15

def extract(root_objects, options = {})
  raise ExtractionError, "Root object cannot be nil" if root_objects.nil?

  root_objects = Array(root_objects)
  
  # Validate that all objects are ActiveRecord instances
  root_objects.each do |obj|
    unless obj.is_a?(ActiveRecord::Base)
      raise ExtractionError, "Object must be an ActiveRecord object, got #{obj.class}"
    end
  end

  # Extract options
  max_depth = options[:max_depth] || config.max_depth
  custom_serializers = options[:custom_serializers] || {}

  start_time = Time.now
  records = []
  visited = Set.new
  circular_references = 0

  begin
    root_objects.each do |root_object|
      # Add the root object itself
      record_key = "#{root_object.class.name}_#{root_object.id}"
      unless visited.include?(record_key)
        records << serialize_record(root_object, custom_serializers)
        visited << record_key
      end

      # Extract related objects
      circular_references += extract_relationships(root_object, records, visited, 1, max_depth, custom_serializers)
    end

    extraction_time = Time.now - start_time
     = (start_time, records, circular_references, max_depth, root_objects)

    {
      'records' => records,
      'metadata' => 
    }
  rescue StandardError => e
    raise ExtractionError, "Failed to extract relationships: #{e.message}"
  end
end

#extract_and_upload_to_s3(root_objects, bucket_name:, s3_key: nil, region: 'us-east-1', options: {}, **s3_options) ⇒ Object



94
95
96
97
# File 'lib/activerecord_graph_extractor/extractor.rb', line 94

def extract_and_upload_to_s3(root_objects, bucket_name:, s3_key: nil, region: 'us-east-1', options: {}, **s3_options)
  s3_client = S3Client.new(bucket_name: bucket_name, region: region, **s3_options)
  extract_to_s3(root_objects, s3_client, s3_key, options)
end

#extract_to_file(root_objects, file_path, options = {}) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/activerecord_graph_extractor/extractor.rb', line 61

def extract_to_file(root_objects, file_path, options = {})
  begin
    result = extract(root_objects, options)
    File.write(file_path, JSON.pretty_generate(result))
    result
  rescue Errno::ENOENT, Errno::EACCES => e
    raise FileError, "Cannot write to file #{file_path}: #{e.message}"
  rescue JSON::GeneratorError => e
    raise JSONError, "Failed to generate JSON: #{e.message}"
  end
end

#extract_to_s3(root_objects, s3_client, s3_key = nil, options = {}) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/activerecord_graph_extractor/extractor.rb', line 73

def extract_to_s3(root_objects, s3_client, s3_key = nil, options = {})
  # Create a temporary file for the extraction
  temp_file = Tempfile.new(['extraction', '.json'])
  
  begin
    # Extract to temporary file
    result = extract_to_file(root_objects, temp_file.path, options)
    
    # Upload to S3
    upload_result = s3_client.upload_file(temp_file.path, s3_key)
    
    # Return combined result
    result.merge({
      's3_upload' => upload_result
    })
  ensure
    temp_file.close
    temp_file.unlink
  end
end