Home

Awesome

ilohv

ilohv is a simple file manager, implemented as a mountable engine for Rails apps.

Dat name, though?

ruby -e "puts 'ilohv'.chars.map { |c| (c.ord - 3).chr }.join"

Usage

ilohv requires Rails version 3.2.1 or higher. This is due to the fact that it uses Rails' ActiveRecord::Store feature which was added in that version.

ilohv uses the Ruby 1.9+ hash syntax so Ruby 1.8 is explicitly not supported.

To use ilohv add it to your Gemfile, configure the URL root in an initializer and mount it in your application:

# Gemfile:
gem 'ilohv', github: 'clemens/ilohv'

# config/initializers/ilohv.rb
Ilohv::Engine.config.url_root = '/admin/files'

# config/routes.rb
mount Ilohv::Engine, at: Ilohv::Engine.config.url_root

Copy the migrations by running Rails' default Rake task for copying engine migrations and run them:

(bundle exec) rake ilohv:install:migrations
(bundle exec) rake db:migrate

Note: You need to run this Rake task whenever you update ilohv to make sure your app has all necessary migrations.

ilohv is then usable at the specified URL root, e.g. http://localhost:3000/admin/files.

Additional configuration

ilohv uses CarrierWave underneath and the configuration is entirely up to you and your application.

There are no assumptions on how or where you want to store your files except for generating unique filenames. This is done to ensure that your application doesn't accidentally overwrite files with the same name if your storage settings don't ensure unique file paths. By default, UUIDs are generated when a file is being created (using SecureRandom.uuid). You can turn UUID-based filenames off or change it by just overriding the Ilohv::FileUploader#filename method:

# config/initializers/ilohv.rb
Ilohv::FileUploader.class_eval do
  def filename
    super # restore default behavior
  end
end

In this case, it's up to your application to ensure that name clashes are prevented.

All other configuration (e.g. where your files are stored, which file types are allowed...) is entirely up to your application.

ilohv will pick up your default CarrierWave configuration if you're already using CarrierWave in your application. Otherwise you can just add an initializer to configure CarrierWave (check the Configuration section of the CarrierWave readme for details).

You can also have a specific configuration for just the Ilohv::FileUploader:

# config/initializers/ilohv.rb
Ilohv::FileUploader.class_eval do
  storage :fog # put files on some cloud provider like S3 instead of a local directory

  def store_dir
    'ilohv_files' # put files in a subdirectory instead of right in the root
  end
end

Again, check the CarrierWave readme for details.

Styling

ilohv sports a simple interface based on Twitter Bootstrap 3 classes. If your application already uses Bootstrap, you should be good to go. If not, you have three options:

API

ilohv provides a simple API that exposes directories and their files as JSON. You can query the API like so:

curl http://localhost:3000/admin/files/path/to/directory.json

Assuming localhost:3000 is the server you're running ilohv on and ilohv is mounted at /admin/files, this returns the contents of the directory located in path/to/directory.

A simplistic API client could look like this:

require 'json'
require 'open-uri'

class Directory
  attr_reader :name, :full_path, :files

  def self.find_by_path(path)
    begin
      new(JSON.parse(open("http://localhost:3000/files/#{path}.json").read))
    rescue
    end
  end

  def initialize(attributes = {})
    @name, @full_path = attributes.values_at('name', 'full_path')
    @files = Array(attributes['files']).map { |file_attributes| OpenStruct.new(file_attributes) }
  end
end

Input validation, authentication/authorization and all that jazz should be done in your application(s) – ilohv just exposes directories, you're responsible for everything else.

TODO

Credits

© 2014 Clemens Kofler, licensed under the MIT License.

I've written this gem as part of a project for The Mobility House. Huge thanks to them for supporting Open Source by encouraging me to publish it.