Progstr Filer is a developer-friendly file hosting platform built specifically for web apps. It lets you easily associate file attachments with your ActiveRecord models and removes the hassle of actually hosting the files yourself.
Setting up the Ruby gem
Bundler makes that all too easy - add this line to your Gemfile
to have the gem pulled into your app and required automatically.
gem "progstr-filer", :require => "progstr-filer"
Credentials
Progstr Filer uses two keys similar to Amazon's cloud services. The access key is a public string that gets rendered publicly in URL's and web pages. We use it to identify your account. The secret key is used to sign and encrypt sensitive data. You should keep it, well, secret.
Provisioning your add-on with Heroku gets you two environment variables: PROGSTR_FILER_ACCESS_KEY
and PROGSTR_FILER_SECRET_KEY
. Add those to your config/environments/production.rb
file:
Progstr::Filer.access_key = ENV['PROGSTR_FILER_ACCESS_KEY']
Progstr::Filer.secret_key = ENV['PROGSTR_FILER_SECRET_KEY']
Defining an uploader
Every attachment can have a specific set of options that take effect while uploading and manipulating it. Those settings get configured via your own class that will extend Progstr::Filer::Uploader
. You could store uploader classes in your app/uploaders
folder. Here is a sample class:
class AvatarUploader < Progstr::Filer::Uploader
#uploader options
end
Associating uploaders with your models
Progstr Filer extends ActiveRecord models and lets you use the has_file
method in class definitions. Here is a User model class that has an avatar image managed as a Progstr Filer attachment via its avatar
property:
class User < ActiveRecord::Base
has_file :avatar, AvatarUploader
end
Note: make sure your database table has an avatar
column created already. Future versions of the progstr-filer
gem will let you generate migrations automatically.
Feeding data to your uploaders
That is easy - all you need is assign a Ruby File object to the uploader property and save the model object:
@user.avatar = uploaded_image_file
@user.avatar.save
Rails can get most of the job done for you automatically if you create a file upload form:
<div class="field">
<%= f.label :avatar %>
<%= f.file_field :avatar %>
</div>
...and create your model from the params hash:
@user = User.new(params[:user])
@user.save
Generating URLs for files
Just use the url
method on your attachments, say @user.avatar.url
. Here is a sample view that generates an img
tag pointing to the avatar image:
<p>
<b>Avatar:</b><br>
<%= image_tag @user.avatar.url, :style => "max-width: 600px; margin: 10px 0px;" %>
</p>
Validation
Users may upload all types of files to your application and it might be a good idea to restrict that to the set of files that your application knows how to process. For example it would not be a good idea to allow non-image file types as an avatar picture. It might be a good idea to disable executable content that might spread malware too. To help with that the progstr-filer
gem currently supports attachment validation according to an extension whitelist through the validates_file_extension_of
method that is available to model objects:
class User < ActiveRecord::Base
has_file :avatar, AvatarUploader
validates_file_extension_of :avatar, :allowed => ["jpg", "png"]
end
In addition you can restrict the file size using validates_file_size_of
:
class User < ActiveRecord::Base
has_file :avatar, AvatarUploader
validates_file_size_of :avatar, :less_than => 1 * 1024 * 1024
end
The example above will not allow files larger than 1 MB. You can specify a lower bound using the :greater_than
option or even pass a numeric range using the :in
option.
Of course, requiring users to always upload a file when saving a model object, use the Rails built-in validates_presence_of
validator:
class User < ActiveRecord::Base
has_file :avatar, AvatarUploader
validates_presence_of :avatar
end
You can pass a custom error message for all validators using the :message
option.
Deleting stale files
Every time you set a new file and save your model, the old file will get scheduled for deletion. The same happens when you destroy
your model. Note that calling delete
for your model will not delete any associated files.
Source code
The progstr-filer
gem is open source and its code is hosted on Github.
All the techniques outlined in this document are available as a fully-functional Rails project on Github too.