class Tori::Backend::S3

Constants

DEFAULT_CONTENT_TYPE

Attributes

bucket[RW]
client[R]

Public Class Methods

new(bucket:, client: nil) click to toggle source

Must be set bucket name.

And it use aws-sdk-core >= 2.0
ENV takes precedence over credentials file and instance profile

example:

Tori.config.backend = Tori::Backend::S3.new(bucket: 'tori_bucket')
# or
Tori.config.backend = Tori::Backend::S3.new(
  bucket: 'tori_bucket',
  client: Aws::S3::Client.new(
    access_key_id: 'your_access_key',
    secret_access_key: 'your_secret_access_key',
    region: 'your-region-1'
  )
)
# File lib/tori/backend/s3.rb, line 32
def initialize(bucket:, client: nil)
  @bucket = bucket
  if client
    unless client.kind_of?(Aws::S3::Client)
      raise TypeError, "client should be instance of Aws::S3::Client or nil"
    end
    @client = client
  else
    region = ENV['TORI_AWS_REGION'] || ENV['AWS_REGION'] || Aws.config[:region]
    @client = if ENV['TORI_AWS_ACCESS_KEY_ID'] && ENV['TORI_AWS_SECRET_ACCESS_KEY']
                Aws::S3::Client.new(
                  access_key_id:     ENV['TORI_AWS_ACCESS_KEY_ID'],
                  secret_access_key: ENV['TORI_AWS_SECRET_ACCESS_KEY'],
                  region:            region,
                )
              else
                # Use instance profile or credentials file (~/.aws/credentials)
                Aws::S3::Client.new(region: region)
              end
  end
end
type_for(path) click to toggle source
# File lib/tori/backend/s3.rb, line 12
def type_for(path)
  (MIME::Types.type_for(path).first || DEFAULT_CONTENT_TYPE).to_s
end

Public Instance Methods

body(filename, **opts) click to toggle source
# File lib/tori/backend/s3.rb, line 108
def body(filename, **opts)
  get(filename, **opts)[:body]
end
copy_object(opts = {}) click to toggle source
# File lib/tori/backend/s3.rb, line 186
def copy_object(opts = {})
  client.copy_object bucket: @bucket, **opts
end
copy_to(filename, tori_file, **opts) click to toggle source
# File lib/tori/backend/s3.rb, line 128
def copy_to(filename, tori_file, **opts)
  copy_object(
    copy_source: "#{bucket}/#{filename}",
    bucket:      bucket,
    key:         tori_file.name,
    **opts,
  )
end
delete(filename) click to toggle source
# File lib/tori/backend/s3.rb, line 91
def delete(filename)
  delete_object key: filename
end
delete_object(opts={}) click to toggle source
# File lib/tori/backend/s3.rb, line 182
def delete_object(opts={})
  client.delete_object bucket: @bucket, **opts
end
exist?(filename = nil) click to toggle source
# File lib/tori/backend/s3.rb, line 95
def exist?(filename = nil)
  head filename
rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NotFound
  false
else
  true
end
Also aliased as: exists?
exists?(filename = nil)
Alias for: exist?
get(filename, **opts) click to toggle source
# File lib/tori/backend/s3.rb, line 112
def get(filename, **opts)
  get_object(key: filename, **opts)
end
get_object(opts={}) click to toggle source
# File lib/tori/backend/s3.rb, line 166
def get_object(opts={})
  client.get_object bucket: @bucket, **opts
end
head(filename = nil, **opts) click to toggle source
# File lib/tori/backend/s3.rb, line 120
def head(filename = nil, **opts)
  if filename
    head_object key: filename, **opts
  else
    head_bucket
  end
end
head_bucket(opts={}) click to toggle source
# File lib/tori/backend/s3.rb, line 174
def head_bucket(opts={})
  client.head_bucket bucket: @bucket, **opts
end
head_object(opts={}) click to toggle source
# File lib/tori/backend/s3.rb, line 170
def head_object(opts={})
  client.head_object bucket: @bucket, **opts
end
open(filename, opts = {}) { |f| ... } click to toggle source
# File lib/tori/backend/s3.rb, line 146
def open(filename, opts = {})
  names = [::File.basename(filename), ::File.extname(filename)]
  tmpdir = opts.delete(:tmpdir)

  if block_given?
    Tempfile.create(names, tmpdir, opts) do |f|
      get_object(key: filename, response_target: f.path)
      yield f
    end
  else
    f = Tempfile.open(names, tmpdir, opts)
    get_object(key: filename, response_target: f.path)
    f
  end
end
otherwise(backend) click to toggle source
# File lib/tori/backend/s3.rb, line 162
def otherwise(backend)
  Chain.new(self, backend)
end
public_url(filename) click to toggle source
# File lib/tori/backend/s3.rb, line 137
def public_url(filename)
  "#{client.config.endpoint}/#{@bucket}/#{filename}"
end
put(filename, body, **opts) click to toggle source
# File lib/tori/backend/s3.rb, line 116
def put(filename, body, **opts)
  put_object key: filename, body: body, **opts
end
put_object(opts = {}) click to toggle source
# File lib/tori/backend/s3.rb, line 178
def put_object(opts = {})
  client.put_object bucket: @bucket, **opts
end
read(filename, **opts) click to toggle source
# File lib/tori/backend/s3.rb, line 104
def read(filename, **opts)
  body(filename, **opts).read
end
url_for(filename, method) click to toggle source
# File lib/tori/backend/s3.rb, line 141
def url_for(filename, method)
  signer = Aws::S3::Presigner.new(client: client)
  signer.presigned_url(method, bucket: @bucket, key: filename)
end
write(filename, resource, opts = nil) click to toggle source
# File lib/tori/backend/s3.rb, line 54
def write(filename, resource, opts = nil)
  opts ||= {}
  if from_path = opts.delete(:from_path)
    opts[:content_type] = self.class.type_for(from_path)
  end

  if resource.nil? && opts[:body]
    resource = opts[:body]
  end

  case resource
  when String
    put_object({
      key: filename,
      body: resource,
      content_type: DEFAULT_CONTENT_TYPE,
    }.merge(opts))
  when File, Pathname
    path = resource.to_path
    content_type = self.class.type_for(path)
    ::File.open(path) { |f|
      put_object({
        key: filename,
        body: f,
        content_type: content_type.to_s,
        content_length: f.size,
      }.merge(opts))
    }
  else
    put_object({
      key: filename,
      body: resource,
      content_type: DEFAULT_CONTENT_TYPE,
    }.merge(opts))
  end
end