Working with UploadColumn: Basics

In this tutorial I'll explain how to set up UploadColumn, how to access and link to files, how to create different versions of the same file, how to use magic columns to store additional information about your file in the database and how to make the temporary storage mechanisms work for you.

Setting up UploadColumn

UploadColumn stores the file you upload to your filesystem, the name of the file will be stored in your database. You'll need to create a column in your database to hold the name of the file, it doesn't need to be terribly long, since only the filename, not the full path will be stored. In this example we have a table called users and we want each user to have an avatar. We create a column called avatar and a model for our table in Rails. If we're using migrations we could have done:

add_column 'users', 'avatar', :string

Now we need to tell Rails that this is an UploadColumn, in your model add the following line:

upload_column :avatar

In HTML, by default, if you have an input field of type file, then if the form it's in is submitted, only the name of the file is sent, not the actual file. Obviously that's not so great.

If you want the actual file to be sent you need to set the encoding of the form to multipart. There is a convenient method in UploadColumn that makes this really easy, instead of your usual form_tag declaration simply use upload_form_tag.

You're all done! Now you can start upoading files to your server, but quite probably you aren't happy with the default settings. Almost everything in UploadColumn can be configured, but lots of configuration can be confusing, let's start with the simple stuff!

image_column

One of the most common tasks on the web is uploading images, UploadColumn includes a number of methods that make working with images easier, so many in fact that I've devoted an entire page to them, check out Working with Images. Just a tidbit:

class User < ActiveRecord::Base
    image_column :avatar
end

There is a special method, image_column for images which prevents the upload of files that aren't images and offers a few other conveniences.

Storage Directories

By default, UploadColumn stores your files in the following kind of directory:

model/attribute/id/filename.jpg

So in our example above, if the user with the id 5 would upload llama.png, the file would be stored at the following location:

user/avatar/5/llama.png

You can pass a :store_dir directive to you upload_column declaration, that way the file will always be stored in that directory. In our above example you could have done:

upload_column :avatar, :store_dir => "avatars"

And the file would have been stored to:

avatars/llama.png

You can also pass a Proc.

You may have noticed that all these directories are relative, but what are they relative to? By default, if you use upload_column they will be relative to your public directory, and if you use image_column they'll be relative to public/images. This can be overwritten via :root_path:

upload_column :avatar, :root_path => File.join(RAILS_ROOT, 'files')

would result in the file being stored at:

files/user/avatar/5/llama.png

Note that :root_path is an absolute directory, that is why you'll probably want to join it with RAILS_ROOT.

Accessing and Linking to Files

You have uploaded your files, so naturally you'll want to access them. The most basic use would be linking to them, obviously, since the main purpose of uploading files usually is for others to download them.

Once you've uploaded a file and you access it in the usual way:

@user = User.find(params[:id])
@user.avatar

An instance of UploadedFile is returned. UploadedFile has a lot of different methods which make it easy to work with the file. For a complete list, see the rdoc. Right now we'll use the url method.

@user.avatar.url

There is more information about the file available, you can use for example path for the complete path or store_dir for the storage directory.

Working with versions

Oftentimes you want to present different versions of the same file, maybe you'll need to somehow parse the file, or show an image in different sizes. UploadColumn makes this easy:

upload_column :avatar, :versions => [ :thumb, :large ]

With image_column you can even do:

image_column :avatar, :versions => { :thumb => 'c100x100', :large => '300x300' }

Note the 'c' before the size string for :thumb, this means that the image will be cropped to exactly 100x100 pixels. The :large version will be no larger than 300x300 pixels but will keep the original aspect ratio. (if it was 640x480 before it will be 300x225 after.)

image_column :avatar, :versions => { :thumb => 'c100x100', :sepia => proc{ |img| img.sepiatone } }

This will sepiatone the :sepia version.

To access these versions you can simply do:

@user.avatar.thumb.url

et cetera.

Using magic columns

The name is somewhat confusing, since UploadColumn uses rmagick (with a k), which is completely different from magic columns. Basically magic columns allow you to store additional information about your file in database columns without doing any heavy lifting. If you did:

upload_column :avatar

You can simply add a column such as avatar_filesize to your database table, and it will automatically be filled with the filesize. Currently the following magic columns work (always substitute avatar for the name of your column):

If you use image_column you can even use: