Class: ActiveRecordGraphExtractor::S3Client

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bucket_name:, region: 'us-east-1', **options) ⇒ S3Client

Returns a new instance of S3Client.



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 9

def initialize(bucket_name:, region: 'us-east-1', **options)
  @bucket_name = bucket_name
  @region = region
  
  # Initialize AWS S3 client with optional credentials
  s3_options = { region: region }
  s3_options.merge!(options) if options.any?
  
  @s3_client = Aws::S3::Client.new(s3_options)
  
  validate_bucket_access!
end

Instance Attribute Details

#bucket_nameObject (readonly)

Returns the value of attribute bucket_name.



7
8
9
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 7

def bucket_name
  @bucket_name
end

#regionObject (readonly)

Returns the value of attribute region.



7
8
9
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 7

def region
  @region
end

#s3_clientObject (readonly)

Returns the value of attribute s3_client.



7
8
9
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 7

def s3_client
  @s3_client
end

Instance Method Details

#delete_file(s3_key) ⇒ Object

Delete a file from S3



109
110
111
112
113
114
115
116
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 109

def delete_file(s3_key)
  begin
    s3_client.delete_object(bucket: bucket_name, key: s3_key)
    true
  rescue Aws::S3::Errors::ServiceError => e
    raise S3Error, "Failed to delete file: #{e.message}"
  end
end

#download_file(s3_key, local_file_path = nil) ⇒ Object

Download a file from S3



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 51

def download_file(s3_key, local_file_path = nil)
  local_file_path ||= File.basename(s3_key)
  
  begin
    s3_client.get_object(
      bucket: bucket_name,
      key: s3_key,
      response_target: local_file_path
    )
    
    {
      bucket: bucket_name,
      key: s3_key,
      local_path: local_file_path,
      size: File.size(local_file_path)
    }
  rescue Aws::S3::Errors::NoSuchKey
    raise S3Error, "File not found in S3: s3://#{bucket_name}/#{s3_key}"
  rescue Aws::S3::Errors::ServiceError => e
    raise S3Error, "Failed to download file from S3: #{e.message}"
  end
end

#file_exists?(s3_key) ⇒ Boolean

Check if a file exists in S3

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 75

def file_exists?(s3_key)
  s3_client.head_object(bucket: bucket_name, key: s3_key)
  true
rescue Aws::S3::Errors::NotFound
  false
rescue Aws::S3::Errors::ServiceError => e
  raise S3Error, "Failed to check file existence: #{e.message}"
end

#file_metadata(s3_key) ⇒ Object

Get file metadata



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 129

def (s3_key)
  begin
    response = s3_client.head_object(bucket: bucket_name, key: s3_key)
    
    {
      key: s3_key,
      size: response.content_length,
      last_modified: response.last_modified,
      content_type: response.content_type,
      etag: response.etag,
      metadata: response.
    }
  rescue Aws::S3::Errors::NotFound
    raise S3Error, "File not found: s3://#{bucket_name}/#{s3_key}"
  rescue Aws::S3::Errors::ServiceError => e
    raise S3Error, "Failed to get file metadata: #{e.message}"
  end
end

#list_files(prefix: nil, max_keys: 1000) ⇒ Object

List files in S3 with optional prefix



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 85

def list_files(prefix: nil, max_keys: 1000)
  options = {
    bucket: bucket_name,
    max_keys: max_keys
  }
  options[:prefix] = prefix if prefix

  begin
    response = s3_client.list_objects_v2(options)
    
    response.contents.map do |object|
      {
        key: object.key,
        size: object.size,
        last_modified: object.last_modified,
        url: s3_url(object.key)
      }
    end
  rescue Aws::S3::Errors::ServiceError => e
    raise S3Error, "Failed to list files: #{e.message}"
  end
end

#presigned_url(s3_key, expires_in: 3600) ⇒ Object

Generate a presigned URL for downloading



119
120
121
122
123
124
125
126
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 119

def presigned_url(s3_key, expires_in: 3600)
  begin
    presigner = Aws::S3::Presigner.new(client: s3_client)
    presigner.presigned_url(:get_object, bucket: bucket_name, key: s3_key, expires_in: expires_in)
  rescue Aws::S3::Errors::ServiceError => e
    raise S3Error, "Failed to generate presigned URL: #{e.message}"
  end
end

#upload_file(local_file_path, s3_key = nil, **options) ⇒ Object

Upload a file to S3

Raises:



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
# File 'lib/activerecord_graph_extractor/s3_client.rb', line 23

def upload_file(local_file_path, s3_key = nil, **options)
  raise FileError, "File not found: #{local_file_path}" unless File.exist?(local_file_path)
  
  s3_key ||= generate_s3_key(local_file_path)
  
  begin
    File.open(local_file_path, 'rb') do |file|
      s3_client.put_object(
        bucket: bucket_name,
        key: s3_key,
        body: file,
        content_type: 'application/json',
        **options
      )
    end
    
    {
      bucket: bucket_name,
      key: s3_key,
      url: s3_url(s3_key),
      size: File.size(local_file_path)
    }
  rescue Aws::S3::Errors::ServiceError => e
    raise S3Error, "Failed to upload file to S3: #{e.message}"
  end
end