class ActiveStorage::Imgur::Service

Attributes

client[R]

Public Class Methods

new(client_id:, client_secret:, refresh_token:, access_token:) click to toggle source
# File lib/active_storage/imgur/service.rb, line 11
def initialize(client_id:, client_secret:, refresh_token:, access_token:)
  @client = ::Imgurapi::Session.instance(
    client_id: client_id, client_secret: client_secret,
    refresh_token: refresh_token, access_token: access_token)
end

Public Instance Methods

delete(key) click to toggle source

Delete the file at the key.

# File lib/active_storage/imgur/service.rb, line 61
def delete(key)
  instrument :delete, key: key do
    map = find_map_by_key(key)
    if map
      client.image.image_delete(map.imgur_id)
      map.destroy!
    end
  end
end
delete_prefixed(prefix) click to toggle source

Delete files at keys starting with the prefix.

# File lib/active_storage/imgur/service.rb, line 72
def delete_prefixed(prefix)
  instrument :delete_prefixed, prefix: prefix do
    maps = ActiveStorage::ImgurKeyMapping.by_prefix_key(prefix)
    maps.each do |map|
      client.image.image_delete(map.imgur_id)
      map.destroy!
    end
  end
end
download(key, &block) click to toggle source

Return the content of the file at the key.

# File lib/active_storage/imgur/service.rb, line 39
def download(key, &block)
  if block_given?
    instrument :streaming_download, key: key do
      stream(key, &block)
    end
  else
    instrument :download, key: key do
      File.binread file_for(key)
    end
  end
end
download_chunk(key, range) click to toggle source

Return the partial content in the byte range of the file at the key.

# File lib/active_storage/imgur/service.rb, line 52
def download_chunk(key, range)
  instrument :download_chunk, key: key, range: range do
    file = file_for(key)
    file.seek range.begin
    file.read range.size
  end
end
exist?(key) click to toggle source

Return true if a file exists at the key.

# File lib/active_storage/imgur/service.rb, line 83
def exist?(key)
  instrument :exist, key: key do |payload|
    id = map_key_to_id(key)
    answer = id.present?

    payload[:exist] = answer
    answer
  end
end
headers_for_direct_upload(key, content_type:, checksum:, **) click to toggle source
# File lib/active_storage/imgur/service.rb, line 130
def headers_for_direct_upload(key, content_type:, checksum:, **)
  { "Content-Type" => content_type, "Content-MD5" => checksum }
end
upload(key, io, checksum: nil, **) click to toggle source

Upload the io to the key specified. If a checksum is provided, the service will ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError.

# File lib/active_storage/imgur/service.rb, line 19
def upload(key, io, checksum: nil, **)
  instrument :upload, key: key, checksum: checksum do
    if io.is_a?(StringIO)
      io = string_io_to_file(key, io)
    end

    ensure_integrity_of(key, io, checksum) if checksum
    image = client.image.image_upload(io)

    ActiveStorage::ImgurKeyMapping.create(key: key, imgur_id: image.id)
  end
rescue StandardError => e
  if e.message.match(/must be an image/)
    raise NotAnImage
  else
    raise e
  end
end
url(key, expires_in:, disposition:, filename:, content_type:) click to toggle source

Returns a signed, temporary URL for the file at the key. The URL will be valid for the amount of seconds specified in expires_in. You must also provide the disposition (:inline or :attachment), filename, and content_type that you wish the file to be served with on request.

# File lib/active_storage/imgur/service.rb, line 96
def url(key, expires_in:, disposition:, filename:, content_type:)
  instrument :url, key: key do |payload|
    image = image_for(key)

    image.link.tap do |url|
      payload[:url] = url
    end
  end
end
url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:) click to toggle source

Returns a signed, temporary URL that a direct upload file can be PUT to on the key. The URL will be valid for the amount of seconds specified in expires_in. You must also provide the content_type, content_length, and checksum of the file that will be uploaded. All these attributes will be validated by the service upon upload.

# File lib/active_storage/imgur/service.rb, line 110
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
  instrument :url, key: key do |payload|
    verified_token_with_expiration = ActiveStorage.verifier.generate(
      {
        key: key,
        content_type: content_type,
        content_length: content_length,
        checksum: checksum
      },
      { expires_in: expires_in,
        purpose: :blob_token }
    )

    generated_url = url_helpers.update_rails_imgur_service_url(verified_token_with_expiration, host: current_host)

    payload[:url] = generated_url
    generated_url
  end
end

Private Instance Methods

current_host() click to toggle source
# File lib/active_storage/imgur/service.rb, line 187
def current_host
  ActiveStorage::Current.host
end
ensure_integrity_of(key, file, checksum) click to toggle source
# File lib/active_storage/imgur/service.rb, line 135
def ensure_integrity_of(key, file, checksum)
  unless Digest::MD5.file(file).base64digest == checksum
    delete key
    raise ActiveStorage::IntegrityError
  end
end
file_for(key) click to toggle source
# File lib/active_storage/imgur/service.rb, line 158
def file_for(key)
  image = image_for(key)
  Down.download(image.link)
end
find_map_by_key(key) click to toggle source
# File lib/active_storage/imgur/service.rb, line 142
def find_map_by_key(key)
  ActiveStorage::ImgurKeyMapping.find_by(key: key)
end
image_for(key) click to toggle source
# File lib/active_storage/imgur/service.rb, line 153
def image_for(key)
  id = map_key_to_id(key)
  client.image.image(id)
end
map_key_to_id(key) click to toggle source
# File lib/active_storage/imgur/service.rb, line 146
def map_key_to_id(key)
  map = find_map_by_key(key)
  if map
    map.imgur_id
  end
end
stream(key) { |read| ... } click to toggle source
# File lib/active_storage/imgur/service.rb, line 171
def stream(key)
  image = image_for(key)
  remote_file = Down.open(image.link)

  chunk_size = 128.kilobytes


  while !remote_file.eof?
    yield remote_file.read(chunk_size)
  end
end
string_io_to_file(key, string_io) click to toggle source
# File lib/active_storage/imgur/service.rb, line 163
def string_io_to_file(key, string_io)
  ext = File.extname(key)
  base = File.basename(key, ext)
  Tempfile.new([base, ext]).tap do |file|
    file.write string_io
  end
end
url_helpers() click to toggle source
# File lib/active_storage/imgur/service.rb, line 183
def url_helpers
  @url_helpers ||= Rails.application.routes.url_helpers
end