Module | FileColumn::ClassMethods |
In: |
lib/file_column.rb
|
The FileColumn module allows you to easily handle file uploads. You can designate one or more columns of your model’s table as "file columns" like this:
class Entry < ActiveRecord::Base file_column :image end
Now, by default, an uploaded file "test.png" for an entry object with primary key 42 will be stored in in "public/entry/image/42/test.png". The filename "test.png" will be stored in the record’s image column.
The methods of this module are automatically included into ActiveRecord::Base as class methods, so that you can use them in your models.
After calling "file_column :image" as in the example above, a number of instance methods will automatically be generated, all prefixed by "image":
You can access the raw value of the "image" column (which will contain the filename) via the ActiveRecord::Base#attributes or ActiveRecord::Base#[] methods like this:
entry['image'] # e.g."test.png"
For a model class Entry and a column image, all files will be stored under "public/entry/image". A sub-directory named after the primary key of the object will be created, so that files can be stored using their real filename. For example, a file "test.png" stored in an Entry object with id 42 will be stored in
public/entry/image/42/test.png
Files will be moved to this location in an after_save callback. They will be stored in a temporary location previously as explained in the next section.
Suppose you have a form for creating a new object where the user can upload an image. The form may have to be re-displayed because of validation errors. The uploaded file has to be stored somewhere so that the user does not have to upload it again. FileColumn will store these in a temporary directory (called "tmp" and located under the column’s base directory by default) so that it can be moved to the final location if the object is successfully created. If the form is never completed, though, you can easily remove all the images in this "tmp" directory once per day or so.
So in the example above, the image "test.png" would first be stored in "public/entry/image/tmp/<some_random_key>/test.png" and be moved to "public/entry/image/<primary_key>/test.png".
This temporary location of newly uploaded files has another advantage when updating objects. If the update fails for some reasons (e.g. due to validations), the existing image will not be overwritten, so it has a kind of "transactional behaviour".
FileColumn allows you to keep more than one file in a directory and will move/delete all the files it finds in a model object’s directory when necessary. You can access these files via the optional suffix parameter that some of the generated methods accept (see above). This suffix is inserted into the filename before the extension, separated by a dash.
Suppose your uploaded file is named "vancouver.jpg" and you want to create a thumb-nail and store it in the same directory. If you cal image("thumb"), you will receive an absolute path for the file "vancouver-thumb.jpg" in the same directory "vancouver.jpg" is stored. Look at the documentation of FileColumn::Magick for more examples.
FileColumn will try to fix the file extension of uploaded files, so that the files are served with the correct mime-type by your web-server. Most web-servers are setting the mime-type based on the file’s extension. You can disable this behaviour by passing the :fix_file_extensions option with a value of nil to file_column.
In order to set the correct extension, FileColumn tries to determine the files mime-type first. It then uses the MIME_EXTENSIONS hash to choose the corresponding file extension. You can override this hash by passing in a :mime_extensions option to file_column.
The mime-type of the uploaded file is determined with the following steps:
MIME_EXTENSIONS | = | { "image/gif" => "gif", "image/jpeg" => "jpg", "image/pjpeg" => "jpg", "image/x-png" => "png", "image/jpg" => "jpg", "image/png" => "png", "application/x-shockwave-flash" => "swf", "application/pdf" => "pdf", "application/pgp-signature" => "sig", "application/futuresplash" => "spl", "application/msword" => "doc", "application/postscript" => "ps", "application/x-bittorrent" => "torrent", "application/x-dvi" => "dvi", "application/x-gzip" => "gz", "application/x-ns-proxy-autoconfig" => "pac", "application/x-shockwave-flash" => "swf", "application/x-tgz" => "tar.gz", "application/x-tar" => "tar", "application/zip" => "zip", "audio/mpeg" => "mp3", "audio/x-mpegurl" => "m3u", "audio/x-ms-wma" => "wma", "audio/x-ms-wax" => "wax", "audio/x-wav" => "wav", "image/x-xbitmap" => "xbm", "image/x-xpixmap" => "xpm", "image/x-xwindowdump" => "xwd", "text/css" => "css", "text/html" => "html", "text/javascript" => "js", "text/plain" => "txt", "text/xml" => "xml", "video/mpeg" => "mpeg", "video/quicktime" => "mov", "video/x-msvideo" => "avi", "video/x-ms-asf" => "asf", "video/x-ms-wmv" => "wmv" | default mapping of mime-types to file extensions. FileColumn will try to rename a file to the correct extension if it detects a known mime-type | |
EXTENSIONS | = | Set.new MIME_EXTENSIONS.values | ||
DEFAULT_OPTIONS | = | { :root_path => File.join(RAILS_ROOT, "public"), :web_root => "", :mime_extensions => MIME_EXTENSIONS, :extensions => EXTENSIONS, :fix_file_extensions => true, # path to the unix "file" executbale for # guessing the content-type of files :file_exec => "file" | default options. You can override these with file_column’s options parameter |