class Shrine::Storage::FileSystem
Attributes
Public Class Methods
Initializes a storage for uploading to the filesystem.
:prefix : The directory relative to ‘directory` to which files will be stored,
and it is included in the URL.
:permissions : The UNIX permissions applied to created files. Can be set to ‘nil`,
in which case the default permissions will be applied. Defaults to `0644`.
:directory_permissions : The UNIX permissions applied to created directories. Can be set to
`nil`, in which case the default permissions will be applied. Defaults to `0755`.
:clean : By default empty folders inside the directory are automatically
deleted, but if it happens that it causes too much load on the filesystem, you can set this option to `false`.
# File lib/shrine/storage/file_system.rb, line 31 def initialize(directory, prefix: nil, clean: true, permissions: 0644, directory_permissions: 0755) if prefix @prefix = Pathname(relative(prefix)) @directory = Pathname(directory).join(@prefix).expand_path else @directory = Pathname(directory).expand_path end @permissions = permissions @directory_permissions = directory_permissions @clean = clean unless @directory.exist? @directory.mkpath @directory.chmod(directory_permissions) if directory_permissions end end
Public Instance Methods
Deletes all files from the directory
. If a block is passed in, deletes only the files for which the block evaluates to true.
file_system.clear! # deletes all files and subdirectories in the storage directory file_system.clear! { |path| path.mtime < Time.now - 7*24*60*60 } # deletes only files older than 1 week
# File lib/shrine/storage/file_system.rb, line 104 def clear!(&condition) if condition list_files(directory) do |path| next unless condition.call(path) path.delete clean(path) if clean? end else directory.children.each(&:rmtree) end end
Delets the file, and by default deletes the containing directory if it’s empty.
# File lib/shrine/storage/file_system.rb, line 85 def delete(id) path = path(id) path.delete clean(path) if clean? rescue Errno::ENOENT end
Deletes the specified directory on the filesystem.
file_system.delete_prefixed("somekey/derivatives/")
# File lib/shrine/storage/file_system.rb, line 95 def delete_prefixed(delete_prefix) FileUtils.rm_rf directory.join(delete_prefix) end
Returns true if the file exists on the filesystem.
# File lib/shrine/storage/file_system.rb, line 69 def exists?(id) path(id).exist? end
Opens the file on the given location in read mode. Accepts additional ‘File.open` arguments.
# File lib/shrine/storage/file_system.rb, line 62 def open(id, **options) path(id).open(binmode: true, **options) rescue Errno::ENOENT raise Shrine::FileNotFound, "file #{id.inspect} not found on storage" end
Returns the full path to the file.
# File lib/shrine/storage/file_system.rb, line 117 def path(id) directory.join(id.gsub("/", File::SEPARATOR)) end
Copies the file into the given location.
# File lib/shrine/storage/file_system.rb, line 50 def upload(io, id, move: false, **) if move && movable?(io) move(io, path!(id)) else IO.copy_stream(io, path!(id)) end path(id).chmod(permissions) if permissions end
If prefix
is not present, returns a path composed of directory
and the given ‘id`. If prefix
is present, it excludes the directory
part from the returned path (e.g. directory
can be set to “public” folder). Both cases accept a `:host` value which will be prefixed to the generated path.
# File lib/shrine/storage/file_system.rb, line 78 def url(id, host: nil, **options) path = (prefix ? relative_path(id) : path(id)).to_s host ? host + path : path end
Protected Instance Methods
Cleans all empty subdirectories up the hierarchy.
# File lib/shrine/storage/file_system.rb, line 124 def clean(path) path.dirname.ascend do |pathname| if dir_empty?(pathname) && pathname != directory pathname.rmdir else break end end end
# File lib/shrine/storage/file_system.rb, line 134 def clean? @clean end
Private Instance Methods
# File lib/shrine/storage/file_system.rb, line 180 def dir_empty?(path) Dir.empty?(path) end
# File lib/shrine/storage/file_system.rb, line 173 def list_files(directory) Pathname("#{directory}/") # add trailing slash to make it work with symlinks .find .each { |path| yield path if path.file? } end
Returns true if the file is a ‘File` or a UploadedFile
uploaded by the FileSystem
storage.
# File lib/shrine/storage/file_system.rb, line 153 def movable?(io) io.respond_to?(:path) || (io.is_a?(UploadedFile) && io.storage.is_a?(Storage::FileSystem)) end
Moves the file to the given location. This gets called by the ‘moving` plugin.
# File lib/shrine/storage/file_system.rb, line 142 def move(io, path) if io.respond_to?(:path) FileUtils.mv io.path, path else FileUtils.mv io.storage.path(io.id), path io.storage.clean(io.storage.path(io.id)) if io.storage.clean? end end
Creates all intermediate directories for that location.
# File lib/shrine/storage/file_system.rb, line 159 def path!(id) path = path(id) FileUtils.mkdir_p(path.dirname, mode: directory_permissions) path end
# File lib/shrine/storage/file_system.rb, line 169 def relative(path) path.sub(%r{^/}, "") end
# File lib/shrine/storage/file_system.rb, line 165 def relative_path(id) "/" + prefix.join(id.gsub("/", File::SEPARATOR)).to_s end