Ron Barry/foodini.org
         Latest Entry
prev:20080828           whole blog            in context             next:20080905
%20080903
...
Since there seems to be little information on how to do it, I would like to
present (actually, there's nothing philanthropic about the documentation
gesture here - I just know for a fact that anywhere that I write this down will
get it lost so I'd better put it here) a solution for uploading files through
the form_for module of Ruby on Rails.

Most of the solutions I've seen are for more advanced users than I, so I'll take
this right from the beginning.

I needed to be able to upload an asset to my RoR application.  Most of my
models, views, and controllers were created using the script/generate.  So the
'asset' view that the 'script/generate scaffold' created looked something like:

<h1>New asset</h1>
<% form_for(@asset) do |f| %>
  <% f.error_messages %>

  <p>
    <%= f.label :smURL %><br />
    <%= f.text_field :smURL %>
  </p>

  ...etc...

I needed two bits in the view, the first was to set up the form to do multipart
encoding.  I replace the form_for line with:

<% form_for(@asset, :html => {:multipart => true}) do |f| %>

...and the new entry for the upload browser:

  <p>
      <%= f.file_field :raw_asset %>
  </p>

That's it.  If you cram that into your view, you'll see the upload box.  Now, on
to the controller.  I didn't change anything at all here, but it is worth noting
that, through a convoluted mess of ruby that I'm not about to grok in this
decade, the first line of the create action,

  @asset = Asset.new(params[:asset])

... goes looking for a method called Asset.raw_asset=.  (As a side note, I hate
trying to put technical tokens into English.  It rubs me the wrong way to follow
an = (which is, in turn, a part of the raw_asset method name) with a period.  I
also seem to have a habit of overusing parentheses.)  Anyway, the place to 
handle this is in your model.  In my case, in asset.rb:

def raw_asset=(arg)
    original_filename = arg.original_filename
    data = arg.read

    #now do whatever you like.  The name of the file on the user's machine is
    #in original_filename and the contents of the file is in data.
end

Seems simple enough, but googling was not as productive as one would expect for
simple a task.

    -rbarry
prev:20080828           whole blog            in context             next:20080905