Class: Saviour::S3Storage

Inherits:
Object
  • Object
show all
Defined in:
lib/saviour/s3_storage.rb

Constant Summary collapse

MissingPublicUrlPrefix =
Class.new(StandardError)
KeyTooLarge =
Class.new(StandardError)

Instance Method Summary collapse

Constructor Details

#initialize(conf = {}) ⇒ S3Storage



11
12
13
14
15
16
17
18
19
20
# File 'lib/saviour/s3_storage.rb', line 11

def initialize(conf = {})
  @bucket = conf.delete(:bucket)
  @public_url_prefix = conf.delete(:public_url_prefix)
  @extra_aws_client_options = conf.delete(:aws_client_opts)
  @conf = conf
  @create_options = conf.delete(:create_options) { {} }
  conf.fetch(:aws_access_key_id) { raise(ArgumentError, "aws_access_key_id is required") }
  conf.fetch(:aws_secret_access_key) { raise(ArgumentError, "aws_secret_access_key is required") }
  @region = conf[:region] || raise(ArgumentError, "region is required")
end

Instance Method Details

#cp(source_path, destination_path) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/saviour/s3_storage.rb', line 87

def cp(source_path, destination_path)
  source_path = sanitize_leading_slash(source_path)
  destination_path = sanitize_leading_slash(destination_path)

  client.copy_object(
    @create_options.merge(
      copy_source: "/#{@bucket}/#{source_path}",
      bucket: @bucket,
      key: destination_path
    )
  )
rescue Aws::S3::Errors::NoSuchKey
  raise FileNotPresent, "Trying to cp an unexisting path: #{source_path}"
end

#delete(path) ⇒ Object



60
61
62
63
64
65
66
67
# File 'lib/saviour/s3_storage.rb', line 60

def delete(path)
  path = sanitize_leading_slash(path)

  client.delete_object(
    bucket: @bucket,
    key: path
  )
end

#exists?(path) ⇒ Boolean



69
70
71
72
73
74
75
76
77
78
# File 'lib/saviour/s3_storage.rb', line 69

def exists?(path)
  path = sanitize_leading_slash(path)

  !!client.head_object(
    bucket: @bucket,
    key: path
  )
rescue Aws::S3::Errors::NotFound
  false
end

#mv(source_path, destination_path) ⇒ Object



102
103
104
105
# File 'lib/saviour/s3_storage.rb', line 102

def mv(source_path, destination_path)
  cp(source_path, destination_path)
  delete(source_path)
end

#public_url(path) ⇒ Object



80
81
82
83
84
85
# File 'lib/saviour/s3_storage.rb', line 80

def public_url(path)
  raise(MissingPublicUrlPrefix, "You must provide a `public_url_prefix`") unless public_url_prefix

  path = sanitize_leading_slash(path)
  ::File.join(public_url_prefix, path)
end

#read(path) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/saviour/s3_storage.rb', line 52

def read(path)
  path = sanitize_leading_slash(path)

  client.get_object(bucket: @bucket, key: path).body.read
rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::NoSuchKey
  raise FileNotPresent, "Trying to read an unexisting path: #{path}"
end

#read_to_file(path, dest_file) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/saviour/s3_storage.rb', line 40

def read_to_file(path, dest_file)
  path = sanitize_leading_slash(path)

  dest_file.binmode
  dest_file.rewind
  dest_file.truncate(0)

  client.get_object({ bucket: @bucket, key: path }, target: dest_file)
rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::NoSuchKey
  raise FileNotPresent, "Trying to read an unexisting path: #{path}"
end

#write(file_or_contents, path) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/saviour/s3_storage.rb', line 22

def write(file_or_contents, path)
  path = sanitize_leading_slash(path)

  # http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
  if path.bytesize > 1024
    raise(KeyTooLarge, "The key in S3 must be at max 1024 bytes, this key is too big: #{path}")
  end

  # TODO: Use multipart api
  client.put_object(@create_options.merge(body: file_or_contents, bucket: @bucket, key: path))
end

#write_from_file(file, path) ⇒ Object



34
35
36
37
38
# File 'lib/saviour/s3_storage.rb', line 34

def write_from_file(file, path)
  file.rewind

  write(file, path)
end