class Safrano::Media::Static

Simple static File/Directory based media store handler similar to Rack::Static with a flat directory structure

Public Class Methods

new(root: nil, mediaklass:) click to toggle source
# File lib/odata/collection_media.rb, line 22
def initialize(root: nil, mediaklass:)
  @root = File.absolute_path(root || Dir.pwd)
  @file_server = ::Rack::File.new(@root)
  @media_class = mediaklass
  @media_dir_name = mediaklass.to_s
  register
end

Public Instance Methods

abs_filename(entity) click to toggle source

absolute filename

# File lib/odata/collection_media.rb, line 78
def abs_filename(entity)
  File.absolute_path(filename(entity), @root)
end
abs_path(entity) click to toggle source

/@root/Photo/1

# File lib/odata/collection_media.rb, line 73
def abs_path(entity)
  File.absolute_path(media_path(entity), @root)
end
create_abs_class_dir() click to toggle source
# File lib/odata/collection_media.rb, line 34
def create_abs_class_dir
  FileUtils.makedirs @abs_klass_dir unless Dir.exist?(@abs_klass_dir)
end
filename(entity) click to toggle source

relative to @root eg Photo/1/1

# File lib/odata/collection_media.rb, line 63
def filename(entity)
  Dir.chdir(abs_path(entity)) do
    # simple design: one file per directory, and the directory
    # contains the media entity-id --> implicit link between the media
    # entity
    File.join(media_path(entity), Dir.glob('*').max)
  end
end
finalize() click to toggle source
# File lib/odata/collection_media.rb, line 38
def finalize
  create_abs_class_dir
end
in_media_directory(entity) { || ... } click to toggle source
# File lib/odata/collection_media.rb, line 89
def in_media_directory(entity)
  mpi = media_directory(entity)
  Dir.mkdir mpi unless Dir.exist?(mpi)
  Dir.chdir mpi do
    yield
  end
end
media_directory(entity) click to toggle source

this is relative to abs_klass_dir(entity) eg to /@root/Photo simplest implementation is media_directory = entity.media_path_id –> we get a 1 level depth flat directory structure

# File lib/odata/collection_media.rb, line 85
def media_directory(entity)
  entity.media_path_id
end
media_path(entity) click to toggle source

this is relative to @root eg. Photo/1

# File lib/odata/collection_media.rb, line 57
def media_path(entity)
  File.join(@media_dir_name, media_directory(entity))
end
odata_delete(entity:) click to toggle source
# File lib/odata/collection_media.rb, line 97
def odata_delete(entity:)
  Dir.chdir(@abs_klass_dir) do
    in_media_directory(entity) do
      Dir.glob('*').each { |oldf| File.delete(oldf) }
    end
  end
end
odata_get(request:, entity:) click to toggle source

minimal working implementation…

Note: @file_server works relative to @root directory
# File lib/odata/collection_media.rb, line 44
def odata_get(request:, entity:)
  media_env = request.env.dup
  media_env['PATH_INFO'] = filename(entity)
  fsret = @file_server.call(media_env)
  if fsret.first == 200
    # provide own content type as we keep it in the media entity
    fsret[1]['Content-Type'] = entity.content_type
  end
  fsret
end
register() click to toggle source
# File lib/odata/collection_media.rb, line 30
def register
  @abs_klass_dir = File.absolute_path(@media_dir_name, @root)
end
replace_file(data:, filename:, entity:) click to toggle source

Here as well, MVP implementation

# File lib/odata/collection_media.rb, line 127
def replace_file(data:, filename:, entity:)
  Dir.chdir(@abs_klass_dir) do
    in_media_directory(entity) do
      version = nil
      Dir.glob('*').sort.each do |oldf|
        version = oldf
        File.delete(oldf)
      end
      filename = (version.to_i + 1).to_s
      File.open(filename, 'wb') { |f| IO.copy_stream(data, f) }
    end
  end
end
ressource_version(entity) click to toggle source

needed for having a changing media ressource “source” metadata after each upload, so that clients get informed about new versions of the same media ressource

# File lib/odata/collection_media.rb, line 118
def ressource_version(entity)
  Dir.chdir(@abs_klass_dir) do
    in_media_directory(entity) do
      Dir.glob('*').max
    end
  end
end
save_file(data:, filename:, entity:) click to toggle source

Here as well, MVP implementation

# File lib/odata/collection_media.rb, line 106
def save_file(data:, filename:, entity:)
  Dir.chdir(@abs_klass_dir) do
    in_media_directory(entity) do
      filename = '1'
      File.open(filename, 'wb') { |f| IO.copy_stream(data, f) }
    end
  end
end