module Shrine::InstanceMethods

Attributes

storage_key[R]

The symbol identifier for the storage used by the uploader.

Public Class Methods

new(storage_key) click to toggle source

Accepts a storage symbol registered in ‘Shrine.storages`.

Shrine.new(:store)
# File lib/shrine.rb, line 184
def initialize(storage_key)
  @storage_key = storage_key.to_sym

  storage # ensure storage is registered
end

Public Instance Methods

extract_metadata(io, **options) click to toggle source

Extracts filename, size and MIME type from the file, which is later accessible through UploadedFile#metadata.

# File lib/shrine.rb, line 228
def extract_metadata(io, **options)
  {
    "filename"  => extract_filename(io),
    "size"      => extract_size(io),
    "mime_type" => extract_mime_type(io),
  }
end
generate_location(io, metadata: {}, **options) click to toggle source

Generates a unique location for the uploaded file, preserving the file extension. Can be overriden in uploaders for generating custom location.

# File lib/shrine.rb, line 222
def generate_location(io, metadata: {}, **options)
  basic_location(io, metadata: metadata)
end
opts() click to toggle source

The class-level options hash. This should probably not be modified at the instance level.

# File lib/shrine.rb, line 238
def opts
  self.class.opts
end
storage() click to toggle source

Returns the storage object referenced by the identifier.

# File lib/shrine.rb, line 191
def storage
  self.class.find_storage(storage_key)
end
upload(io, **options) click to toggle source

The main method for uploading files. Takes an IO-like object and an optional context hash (used internally by Shrine::Attacher). It calls user-defined process, and afterwards it calls store. The ‘io` is closed after upload.

uploader.upload(io)
uploader.upload(io, metadata: { "foo" => "bar" })           # add metadata
uploader.upload(io, location: "path/to/file")               # specify location
uploader.upload(io, upload_options: { acl: "public-read" }) # add upload options
# File lib/shrine.rb, line 204
def upload(io, **options)
  _enforce_io(io)

  metadata = get_metadata(io, **options)
  location = get_location(io, **options, metadata: metadata)

  _upload(io, **options, location: location, metadata: metadata)

  self.class::UploadedFile.new(
    id:       location,
    storage:  storage_key,
    metadata: metadata,
  )
end

Private Instance Methods

_enforce_io(io) click to toggle source

Asserts that the object is a valid IO object, specifically that it responds to ‘#read`, `#eof?`, `#rewind`, `#size` and `#close`. If the object doesn’t respond to one of these methods, a Shrine::InvalidFile error is raised.

# File lib/shrine.rb, line 308
def _enforce_io(io)
  missing_methods = %i[read eof? rewind close].select { |m| !io.respond_to?(m) }
  raise InvalidFile.new(io, missing_methods) if missing_methods.any?
end
_upload(io, location:, metadata:, upload_options: {}, close: true, delete: false, **) click to toggle source
# File lib/shrine.rb, line 244
def _upload(io, location:, metadata:, upload_options: {}, close: true, delete: false, **)
  storage.upload(io, location, shrine_metadata: metadata, **upload_options)
ensure
  io.close             if close
  File.unlink(io.path) if delete && io.respond_to?(:path) && File.exist?(io.path)
end
basic_location(io, metadata:) click to toggle source

Generates a basic location for an uploaded file

# File lib/shrine.rb, line 274
def basic_location(io, metadata:)
  extension   = ".#{io.extension}" if io.is_a?(UploadedFile) && io.extension
  extension ||= File.extname(metadata["filename"].to_s).downcase
  basename    = generate_uid(io)

  basename + extension
end
extract_filename(io) click to toggle source

Attempts to extract the appropriate filename from the IO object.

# File lib/shrine.rb, line 252
def extract_filename(io)
  if io.respond_to?(:original_filename)
    io.original_filename
  elsif io.respond_to?(:path) && io.path
    File.basename(io.path)
  end
end
extract_mime_type(io) click to toggle source

Attempts to extract the MIME type from the IO object.

# File lib/shrine.rb, line 261
def extract_mime_type(io)
  if io.respond_to?(:content_type) && io.content_type
    Shrine.warn "The \"mime_type\" Shrine metadata field will be set from the \"Content-Type\" request header, which might not hold the actual MIME type of the file. It is recommended to load the determine_mime_type plugin which determines MIME type from file content."
    io.content_type.split(";").first # exclude media type parameters
  end
end
extract_size(io) click to toggle source

Extracts the filesize from the IO object.

# File lib/shrine.rb, line 269
def extract_size(io)
  io.size if io.respond_to?(:size)
end
generate_uid(io) click to toggle source

Generates a unique identifier that can be used for a location.

# File lib/shrine.rb, line 314
def generate_uid(io)
  SecureRandom.hex
end
get_location(io, location: nil, **options) click to toggle source

Retrieves the location for the given IO and context. First it looks for the ‘:location` option, otherwise it calls generate_location.

# File lib/shrine.rb, line 299
def get_location(io, location: nil, **options)
  location ||= generate_location(io, **options)
  location or fail Error, "location generated for #{io.inspect} was nil"
end
get_metadata(io, metadata: nil, **options) click to toggle source

If the IO object is a Shrine::UploadedFile, it simply copies over its metadata, otherwise it calls extract_metadata.

# File lib/shrine.rb, line 284
def get_metadata(io, metadata: nil, **options)
  if io.is_a?(UploadedFile) && metadata != true
    result = io.metadata.dup
  elsif metadata != false
    result = extract_metadata(io, **options)
  else
    result = {}
  end

  result = result.merge(metadata) if metadata.is_a?(Hash)
  result
end