Recipe 14.8. Uploading Files with file_column


Problem

You want to add file upload support to your application with as little effort as possible.

Solution

Install the file_column plug-in to add file uploading and retrieval capabilities to your application's model. Start by installing the plug-in; then, go to your application's vendor/plugins directory and check out the latest version of the plug-in into a directory called file_column.

~/vendor/plugins$ svn co \ > http://opensvn.csie.org/rails_file_column/plugins/file_column/\ > tags/rel_0-3-1/ file_column             

The next step is to test-run the plug-in's unit tests. This is important because file_column assumes that RMagick has been installed. To run the tests using MySQL, update connection.rb with your test database name and your connection information:

vendor/plugins/file_column/test/connection.rb:

print "Using native MySQL\n" require 'logger' ActiveRecord::Base.logger = Logger.new("debug.log") db = 'cookbook_test' ActiveRecord::Base.establish_connection(   :adapter  => "mysql",   :host     => "localhost",   :username => "rails_user",    :password => "r8!lz",   :database => db )

Once the plug-in is installed with passing tests, modify the model that is to have uploaded files associated with it. In this case, create a migration that adds an image column to the users table, allowing users to upload images as part of their profile.

db/migrate/002_add_image_column.rb:

class AddImageColumn < ActiveRecord::Migration   def self.up     add_column :users, :image, :text   end   def self.down     drop_column :users, :image   end end

Now, in the User class definition, define the image column as the file_column. This column stores the location of uploaded images on disk:

app/models/user.rb:

class User < ActiveRecord::Base   file_column :image end

Assuming you have basic scaffolding set up for the User model, you need to modify the update and create forms to handle file uploads. Change the form tag in new.rhtml to:

<% form_tag({:action       => 'create'}, :multipart => true) do %>

Make a similar change in edit.rhtml:

<% form_tag({:action       => 'update'}, :multipart => true) do %>

With the form tags updated with the :multipart option, add the file upload form tag to the _form.rhtml partial:

app/views/users/_form.rhtml:

<%= error_messages_for 'user' %> <!--[form:user]--> <p><label for="user_login">Login</label><br/> <%= text_field 'user', 'login'  %></p>   <p><label for="user_email">Email</label><br/> <%= text_field 'user', 'email'  %></p>   <p><label for="user_image">Image</label><br/> <%= file_column_field 'user', 'image' %></p> <!--[eoform:user]-->

Finally, use the url_for_file_column view helper to display the image. This helper is used with the image_tag helper to generate an image tag. The arguments to url_for_file_column are the name of the model object and the field associated with file uploads.

app/views/users/show.rhtml:

<% for column in User.content_columns %> <p>   <b><%= column.human_name %>:</b> <%=h @user.send(column.name) %> </p> <% end %> <%= image_tag url_for_file_column('user', 'image') %> <%= link_to 'Edit', :action => 'edit', :id => @user %> | <%= link_to 'Back', :action => 'list' %>

Discussion

If you want to ensure that the uploaded images are no taller or wider than 100 pixels, change the call to file_column to:

file_column :image, :magick => {:geometry => "100x100>"}

With the :magick parameter, file_column leaves images alone if they are smaller than 100 x100 pixels. Larger images are scaled so they are smaller than 100 x100, preserving their original proportions. For example, an image that's 50 x200 pixels is resized to 25 x100. It's also possible to generate a number of different version (image sizes) as images are uploaded. Change the file_column call to:

file_column :image, :magick => {:versions =>   { "thumb" => "50x50", "medium" => "640x480>" } }

Now, when an image named test.jpg is uploaded that's larger than 640 x480, three images will resultthe original and two smaller versions:

./public/user/image/7$ ls -1 test-medium.jpg test-thumb.jpg test.jpg

To display the resized versions of the image, pass the version name as the third parameter to url_for_file_column. Here's how to display all three versions of the images in users/show.rhtml:

<p><%= image_tag url_for_file_column('user', 'image') %></p> <p><%= image_tag url_for_file_column('user', 'image', 'thumb') %></p> <p><%= image_tag url_for_file_column('user', 'image', 'medium') %></p>

This plug-in stores images in disk; the database holds only pointers to the file location. This is the method of storage is more common than holding the files directly in the database.

To learn more about this plug-in's options, generate the plug-in's RDoc:

$ rake doc:plugins             

Next, point a browser at ./doc/plugins/file_column/index.html.

See Also

  • The acts_as_attachment plug-in home page,

    http://technoweenie.stikipad.com/plugins/show/Acts+as+Attachment



Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net