Tuesday, 5 December 2006

Moist file upload

Cool, so I just figured out how to integrate file-upload with moist scaffold. If you can already do this while standing on your head - well, why are you reading my blog? ;) Otherwise, here are the basic steps:

Generate a moist scaffold

This can be done as per my previous post. You have to generate it using less_dry so that you can extend the create/update actions in the controller. Also - make sure your model has a string column to hold the filename - I'll assume that this is called "thumbnail" from now on.

Configure the column

In your model file you need to update the filename-column's has_column details to something similar to this:

  has_column "thumbnail",{
    :in_list => true,
    :sortable => false,
    :filterable => false,
    :type => :custom
  }

The important bit being being the :type => :custom. This tells dry_scaffold to go look in the helper for methods that generate the edit-field and list-display. If we were to filter on this column, we could also specify a filter-function, but I haven't done this. I've turned off filtering and sorting for this column - though I could have done a filter/sort on the filename.

Put list/edit methods into the helper

module ThingyHelper
    def thumbnail_edit(one_row, column)
        file_field "thingy", "thumbfile"
    end
    def thumbnail_list(one_row)
        image_tag "/images/thumbnails/#{one_row.thumbnail}", :size => "64x64"
    end
end

These are the methods I mentioned above. The edit method creates a file upload field that is named *differently* to the column that will store the eventual URL. If you want to store the whole image file into the db - go ahead, but I figured it'd be nicer to put them into an images directory.

The list method just displays the file squished into 64x64. It'd be nicer to work some RMagick, but I didn't bother for this example. Note: the reference to one_row is a hack - this is how dry_scaffold refers to the current row of the list. To access other values out of the row, you have to use it - but it seems brittle to me.

Update controller+model to manipulate image

When the user does a browse/upload on a file - it passes the StringIO object through to the controller. This file needs to be saved into the images directory - and just the URL put into the db.

Other sites have covered this already (in a variety of forms): read the rails article here (you may need to go back to a non-spam version). Pick a favourite way and you're done.

No comments: