Introduction
Most web applications today need the capability of
uploading documents, photos and files of various formats.
The active community around Rails has built some great
plugins to carry out these operations with substantial
ease.
As a use case, we will continue building our employee
management system. Here, each employee needs to upload their
photo in order to complete their records. They help to
upload files on a file system, database or a cloud storage
like Amazon S3.
Getting the Prerequisites Right
Install a graphics library that facilitates the
recognition of image formats. Imagemagick is the most commonly used graphics library
and for our sample we will use that. Download the Windows
binary and follow the setup which is pretty straight
forward. We will also need to install a Ruby wrapper around
Imagemagick in order to make your Rails application
understand the Imagemagick libraries.
C:> gem install rmagick
For Linux systems ensure that you compile Imagemagick
from source and for Windows you can download the compatible
bundle of Imagemagick and Rmagick. Many people run into
compatibility issues between these two before getting it
right. You can also look at minimagick as an alternative
which uses less memory than rmagick.
Installing the RoR Plugin
In order to install the plugin, take the URL of the
source repository and run the plugin installation command as
in figure 1.

Figure 1
C:> ruby script/plugin install git://github.com/technoweenie/attachment_fu.git
This creates a folder under the vendor/plugins directory
and contains all the plugin code.
Get your Upload Box and Button
We will start by creating an upload form.
Attachment_fu uses two parts in its form:
<%= f.file_field :uploaded_data %>
This method looks for the appropriate file to be uploaded
in the system. Once this is added, we will be able to browse
the file system and select the file to be uploaded.
Internally it uses file_field helper class.
The second part of the form is as follows:
<% form_for(:uploads, :url => upload_path,
:html => { :multipart => true }) do |f| -%>
The URL directive in this looks for the Restful route of
the uploaded file and sends the uploaded file as a
Post Form Request. The :multipart
=> true method generates the form data which needs
to sent over the Post.
Hence, the overall form looks like this:
<%= error_messages_for :uploads %>
<% form_for(:uploads, :url => upload_path,
:html => { :upload => true }) do |f| -%>
<p>
<label for="upload">Please Upload Your Photo:</label>
<%= f.file_field :uploaded_data %>
</p>
<p>
<%= submit_tag 'Create' %>
</p>
<% end -%>
Prepare the Database and Validate the Uploads
We will start by creating a model and will also generate
a migration.
C:> ruby script/generate model upload

Figure 2
The migration file will have the table definition. We will
store all the attribute information regarding the filename
in the table.
Here is how we do that in
20091119052703_create_uploads.rb:
class CreateUploads < ActiveRecord::Migration
def self.up
create_table :uploads do |t|
t.column :user_id, :integer
t.column :content_type, :string
t.column :filename, :string
t.column :thumbnail, :string
t.column :size, :integer
t.column :width, :integer
t.column :height, :integer
t.timestamps
end
end
def self.down
drop_table :uploads
end
end
Content type column stores the file mime type and checks
if it is an image, document or PDF, filename as it says
stores the name of the file. A thumbnail is generated for
the file so as to add it to places where need to add the
download link to the file. Size, width and height are image
specific attributes and pertain to the file type.
The Upload model essentially contains all the attribute
definitions and information that needs to be known while an
upload is going on.
class Upload < ActiveRecord::Base
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 800.kilobytes,
:resize_to => '200x150>',
:thumbnails => { :thumb => '80x80>' }
validates_as_attachment
end
has_attachment is the magical method, it
contains all the information that our
attachment_fu requires in order to give a
desired result to our image upload. Lets look at some of the
terminology associated with it.
- :content_type - It defines weather we are uploading an
image, a document, or a video.
- :min_size and :max_size defines the minimum and maximum
limits of the file size.
- :size overrides the min_size and max_size directives and
gives a range of sizes like 200..300.
- :resize_to gives the size of the resultant image, the
size to which the image will resize to once it is
uploaded.
- :thumbnails provides the size of the thumbnails to be
generated and displayed as the download file option.
- :path_prefix allows you to add a custom path on the file
system for the storage of the file.
- :storage puts the storage system to be used like Amazon
S3 or a normal file system.
- :processor defines the image processor like rmagick,
minimagick.
Now that we have defined where to upload and what to
upload, we will add the control as to how to upload.
The Create Method

Figure 3
Create the controller with:
C:> ruby script/generate controller uploads
And add the generate create method to it.
class UploadsController < ApplicationController
def new
@upload = Upload.new
end
def create
@upload = Upload.new(params[:upload])
if @upload.save
flash[:notice] = 'Your Photo was successfully Uploaded.'
redirect_to upload_url(@upload)
else
render :action => :new
end
end
end
This method, creates a new record in the database once
the upload is done, and on saving it redirects to the page
where the uploaded file will be displayed.
Now, we know what we have done. In the front end we will
see a thumbnail, the database contains the attributes of the
file and we will, in the back end, refer to the absolute path
of the file on the file system.
<h1>Employee Photos</h1>
<% for uploads in @uploads -%>
<%= link_to image_tag(upload.public_filename(:thumb)), upload.public_filename %>
<% end -%>
There are other methods to add file uploads like the
Paperclip plugin which again is a very simple way to do it.
You can check paper clip out here.
Conclusion
File uploads can be done in Rails using plugins. They
provide an easy and straightforward way to add file uploads
to your app. In our next articles and will look at various
methods of testing our Ruby on Rails app. Stop by next week
and check it out.
Original article