class Dis::Layer

Dis Layer

Represents a layer of storage. It’s a wrapper around Fog::Storage, any provider supported by Fog should be usable.

Options

Examples

This creates a local storage layer. It’s a good idea to have a local layer first, this provides you with a cache on disk that will be faster than reading from the cloud.

Dis::Layer.new(
  Fog::Storage.new({
    provider: 'Local',
    local_root: Rails.root.join('db', 'dis')
  }),
  path: Rails.env
)

This creates a delayed layer on Amazon S3. ActiveJob will kick in and and transfer content from one of the immediate layers later at it’s leisure.

Dis::Layer.new(
  Fog::Storage.new({
    provider:              'AWS',
    aws_access_key_id:     YOUR_AWS_ACCESS_KEY_ID,
    aws_secret_access_key: YOUR_AWS_SECRET_ACCESS_KEY
  }),
  path: "my_bucket",
  delayed: true
)

Attributes

connection[R]

Public Class Methods

new(connection, options = {}) click to toggle source
# File lib/dis/layer.rb, line 52
def initialize(connection, options = {})
  options     = default_options.merge(options)
  @connection = connection
  @delayed    = options[:delayed]
  @readonly   = options[:readonly]
  @public     = options[:public]
  @path       = options[:path]
end

Public Instance Methods

delayed?() click to toggle source

Returns true if the layer is a delayed layer.

# File lib/dis/layer.rb, line 62
def delayed?
  @delayed
end
delete(type, key) click to toggle source

Deletes a file from the store.

layer.delete("documents", key)

Returns true if the file was deleted, or false if it could not be found. Raises an error if the layer is readonly.

# File lib/dis/layer.rb, line 145
def delete(type, key)
  raise Dis::Errors::ReadOnlyError if readonly?

  debug_log("Delete #{type}/#{key} from #{name}") do
    delete!(type, key)
  end
end
existing(type, keys) click to toggle source

Returns all the given keys that exist in the layer.

layer.existing("documents", keys)
# File lib/dis/layer.rb, line 108
def existing(type, keys)
  return [] if keys.empty?

  list = directory(type, keys.first).files.map(&:key)

  keys.select { |key| list.include?(key_component(type, key)) }
end
exists?(type, key) click to toggle source

Returns true if a object with the given key exists.

layer.exists?("documents", key)
# File lib/dis/layer.rb, line 119
def exists?(type, key)
  if directory(type, key)&.files&.head(key_component(type, key))
    true
  else
    false
  end
end
get(type, key) click to toggle source

Retrieves a file from the store.

layer.get("documents", key)
# File lib/dis/layer.rb, line 130
def get(type, key)
  dir = directory(type, key)
  return unless dir

  debug_log("Get #{type}/#{key} from #{name}") do
    dir.files.get(key_component(type, key))
  end
end
immediate?() click to toggle source

Returns true if the layer isn’t a delayed layer.

# File lib/dis/layer.rb, line 67
def immediate?
  !delayed?
end
name() click to toggle source

Returns a name for the layer.

layer.name # => "Fog::Storage::Local::Real/development"
# File lib/dis/layer.rb, line 156
def name
  "#{connection.class.name}/#{path}"
end
public?() click to toggle source

Returns true if the layer is public.

# File lib/dis/layer.rb, line 72
def public?
  @public
end
readonly?() click to toggle source

Returns true if the layer is read only.

# File lib/dis/layer.rb, line 77
def readonly?
  @readonly
end
store(type, key, file) click to toggle source

Stores a file.

key = Digest::SHA1.file(file.path).hexdigest
layer.store("documents", key, path)

The key must be a hex digest of the file content. If an object with the supplied hash already exists, no action will be performed. In other words, no data will be overwritten if a hash collision occurs.

Returns an instance of Fog::Model, or raises an error if the layer is readonly.

# File lib/dis/layer.rb, line 97
def store(type, key, file)
  raise Dis::Errors::ReadOnlyError if readonly?

  debug_log("Store #{type}/#{key} to #{name}") do
    store!(type, key, file)
  end
end
writeable?() click to toggle source

Returns true if the layer is writeable.

# File lib/dis/layer.rb, line 82
def writeable?
  !readonly?
end

Private Instance Methods

default_options() click to toggle source
# File lib/dis/layer.rb, line 162
def default_options
  { delayed: false, readonly: false, public: false, path: nil }
end
delete!(type, key) click to toggle source
# File lib/dis/layer.rb, line 174
def delete!(type, key)
  return false unless exists?(type, key)

  get(type, key).destroy
end
directory(type, key) click to toggle source
# File lib/dis/layer.rb, line 180
def directory(type, key)
  connection.directories.get(directory_component(type, key))
end
directory!(type, key) click to toggle source
# File lib/dis/layer.rb, line 184
def directory!(type, key)
  dir = directory(type, key)
  dir ||= connection.directories.create(
    key: directory_component(type, key),
    public: public?
  )
  dir
end
directory_component(_type, _key) click to toggle source
# File lib/dis/layer.rb, line 166
def directory_component(_type, _key)
  path || ""
end
key_component(type, key) click to toggle source
# File lib/dis/layer.rb, line 170
def key_component(type, key)
  [type, key[0...2], key[2..key.length]].compact.join("/")
end
path() click to toggle source
# File lib/dis/layer.rb, line 204
def path
  @path.presence
end
store!(type, key, file) click to toggle source
# File lib/dis/layer.rb, line 193
def store!(type, key, file)
  return get(type, key) if exists?(type, key)

  file.rewind if file.respond_to?(:rewind)
  directory!(type, key).files.create(
    key: key_component(type, key),
    body: (file.is_a?(Fog::Model) ? file.body : file),
    public: public?
  )
end