Caution! - Many of these posts are creepy-old in the Ruby on Rails world (before 1.0!)
The :author => Charles Abbott now blogs here

file_field_tag, File.size, File.path, FileUtils.mv

2006-05-15   [ 7 comments ]

So, here I am writing another post that digs deeper into the world of Ruby. My goal is now set - in 40 days I, along with my friend Jim, will create a full featured Content Management System on Rails to use on our sites. Of course, the CMS won't be complete in 40 days but I plan on having a working version of it running on one of my personal sites - which does require quite a bit, considering the amount of custom PHP development I put into it.

Today I am going to cover the basics of file uploading - reason being I only know the basics.

Before you can upload a file (outside of ftp) you need to have some html form to allow browsing and selecting of files. To create the form follow the standard rails conventions for form creation:

<%= start_form_tag( {:action => "index"}, {:multipart => "true"}, {:id => "files"}) %>
File to Upload <%= file_field_tag "file" %>
<%= submit_tag %>
<%= end_form_tag %>

You will notice two things about the form above - 1st: {:action => "index"} -and- {:multipart => true } are seperated because they are required as seperate option arrays. 2nd: file_field_tag "file" -sets the name and id to "file", in case you need to access it via the DOM.

Now that you have your form that can submit mixed content we need to scratch the surface of Ruby file handling. And, yes, we will be working more with Ruby than we will Rails - but don't fear it will be fun!

So now that you have pulled out your Ruby Corelib pocket reference (what you don't have one~? ), flip over to the class File and begin reading. Here is where we will be interacting with our uploaded file - through the appropriate File Class.

Enough small talk, what did I do first? Well, I just wanted to see if my files were actually submitting, and what better way than:

if params[:file]
@thefile = File.size(params[:file])
end

This brief code checks the file size of whatever I submitted in the form above. Nestle this snippet in the target method of your controller and you are almost ready to submit. But you have to place the contents of @thefile somewhere so you can see it. So I threw that instance variable into my view and viola~ I started seeing filesizes.

Well that is great - I know my files are going somewhere - so to further quench my curiosity I had to know where they were going. Leave it to Ruby to already have a public Class method ready for me:

@thenewfile = params[:file].path

Since params[:file] is holding the uploaded file - it is no problem treating it like an instance of the File class - call its method .path and print it in your view. I was happy to see something similar to "/tmp/CGI1175.0" (more accurate picture below). Well, that is great - the file is hitting my /tmp directory - so it should be no problem manipulating it.

Now enter the FileUtils Class, and its ton-o-methods. For today's post I will only cover one method (as I am sure I will cover the others as days go by), FileUtils.mv

FileUtils.mv(@thenewfile, "/home/www/www.forthecode.com/web/uploads/firstupload.png")

FileUtils.mv another Ruby Core Class is, as its name suggests, the equivilant to the Unix mv command. Since I had already stored the filepath in @thenewfile, I was able to submit it as the first argument to .mv(sourcefile, destinationfile)

After moving the file my public uploads directory had a file listing of:

Well that is all I have for today - as you can see we have just barely scratched the surface of file handling. We need to chown our content and also do more to track what we are uploading (store some data in the database), as well as handle any potential problematic files and errors. Well, plenty for tomorrow and the next day. Until then - happy coding =)

:author => "Charles Abbott"
Converting to Ruby on Rails
 


Charles said:

Hmmm.. just noticed that the image I am extracting from the database is not showing up properly on this page (I havent dealt with images much, but I guess I cannot use a path relative to the public_html root directory). Interesting - will fix later.

2006-05-16 10:07:03 UTC

Charles said:

Silly me... use absolute path instead of relative, since i cant use the image helper tag in this situation (or can i?)

2006-05-17 21:45:23 UTC

Anonymous said:

"through the appropriate File Class." the docs say the same thing. but really its a TempFile. File doesnt respond to path..

2006-07-22 13:51:28 UTC

Charles said:

Oops, an oversight on my part. I never even saw 'TempFile' in the Ruby Core Lib until reading this comment.

Thanks for the hint - I will no doubt need to look into this more.

I thought I was getting the path from File (and you can use the .path method of File), but in this situation I was wrong! - TempFile.path!

2006-06-01 11:36:24 UTC

Ross said:

Are you putting the FileUtils.mv in the controller or the view?

2006-06-06 19:11:54 UTC

Charles said:

You can put it in either the controller, or if you have a model you can place it there. In this example I had it in the controller, later I moved it out to an Uploads model where I interact with the database a bit more.

2006-06-07 20:08:58 UTC

Charles said:

If you are looking for a Model to handle file uploads check out my newer post "reverse! && a simple file Upload Class"

2006-08-18 09:50:38 UTC

What?

Who?              Link?



Frameworks Good or Bad?   :date => "2007-10-06"
Where is ForTheCode.com Going?   :date => "2007-09-23"
Refactoring - Vital to Software Development   :date => "2007-09-23"
Mongrel Cluster a quick note - and extra notes   :date => "2007-05-20"
Linux Mongrel and Rails   :date => "2007-05-15"
form_remote_tag revisited   :date => "2007-01-07"
How To: Ubuntu 6.10 Edgy on Rails part 3   :date => "2006-12-30"
How To: Ubuntu 6.10 Edgy on Rails part 2   :date => "2006-12-24"
How To: Ubuntu 6.10 Edgy on Rails   :date => "2006-12-22"
verify ... 5.times do cycle   :date => "2006-09-25"
country_select, country_options_for_select, mail_to   :date => "2006-09-05"
Generate and Send Email in Rails   :date => "2006-08-26"
FDF Model, gsub, and send_data   :date => "2006-08-18"
Active Directory Authentication with acts_as_authenticated   :date => "2006-08-17"
Apache2 proxy with Lighttpd - FastCGI for Rails   :date => "2006-08-08"
reverse! && a simple file Upload Class   :date => "2006-07-29"
send_file - a link to download a file   :date => "2006-07-24"
Environments (production, development, test) and cache_pages   :date => "2006-07-04"
.class .methods .instance_variables   :date => "2006-06-14"
select_tag :multiple => true   :date => "2006-06-01"
FileUtils, action_controller rescues   :date => "2006-05-20"
file_field_tag, File.size, File.path, FileUtils.mv   :date => "2006-05-15"
javascript_include_tag, stylesheet_link_tag   :date => "2006-05-02"
submit_to_remote, form_remote_tag, script.aculo.us   :date => "2006-04-30"
periodically_call_remote, simple_format   :date => "2006-04-26"
observe_field - Ajax!   :date => "2006-04-21"
h method, TextHelper, sanitize(), strip_tags()   :date => "2006-04-15"
Rails API :My API [.count(), link_to, text_area :size]   :date => "2006-04-13"
Rails - HTML Select Tag   :date => "2006-04-05"
Pruning Old Sessions   :date => "2006-03-21"
If Elsif Else, and Searching Too!   :date => "2006-03-17"
SHA1 - A quick update   :date => "2006-03-15"
Initialized! good, Authorized? Great! part 2   :date => "2006-03-11"
Initialized! good, Authorized? Great!   :date => "2006-03-08"
Forms and Routing in RoR   :date => "2006-03-06"
My First RoR Post !   :date => "2006-03-05"