Posts tagged attachment_fu

Migrating from attachment_fu to paperclip

Thoughtbot have released a suite of plugins over the past few months that are enlivening the fields of Ruby on Rails file attachments (paperclip) and authentication (clearance), long dominated by Rick Olson’s attachment_fu and restful_authentication. You can see some previous posts about attachment_fu here and here.

I’ve been playing with paperclip on a couple of projects, including one which was previously using attachment_fu. That necessitated some work migrating the previous attachments. Opinions are divided on whether data should be transformed in migrations or in separate libraries, and I’d rather remain agnostic on that, but I whipped together some code that can be used either in migrations or an external library to make the transfer.

You can find it as a gist.

To use it, do something like:

class ConvertAvatar < ActiveRecord::Migration
  include PaperclipMigrations
 
  def self.up
    add_paperclip_fields :users, :photo
    User.reset_column_information
    User.all.each do |user|
      populate_paperclip_from_attachment_fu(user, user.avatar, 'photo') if user.avatar
    end
  end
end

It’s quick and a little dirty, but it’s done the job for me. If you’re using S3 for storage, you might prefer to check out Andrew Timberlake’s writeup.

Announcing image_associations

Discussions of multi-model forms and nested models in Rails has been revived recently, with various changes appearing in Edge Rails, plugins like attribute_fu getting a lot of attention, and the release of ActivePresenter. It looks like when the dust settles we’ll have a nice new set of ways to simplify our code.

One thing I frequently find myself doing is associating multiple images with a given model. My news story might have a banner image, and a series of other attachments, which I could specify with:

class Story < ActiveRecord::Base
  belongs_to :banner_image
  has_many :story_attachments
end
 
class BannerImage < ActiveRecord::Base
  has_attachment # I'm using attachment_fu
end
 
class StoryAttachment < ActiveRecord::Base
  has_attachment # I'm using attachment_fu
end

(or I could use has_one in place of belongs_to there, your tastes/requirements may vary)

What quickly becomes a pain is assigning the images to the models, and having rejected fat controllers I often end up writing accessors on my models to manage that for me:

class Story < ActiveRecord::Base
  belongs_to :banner_image
  has_many :story_attachments
 
  def banner_image(data)
    if valid_file?(data)
      self.banner_image = BannerImage.create(:uploaded_data => data)
    end
  end
 
  def valid_file?
    # etc.
  end
end

That quickly gets dull, so I've wrapped it up in a plugin I'm calling image_associations. With that I can write:

class Story < ActiveRecord::Base
  belongs_to_image :banner_image
  has_many_images :story_attachments
end

and get the accessors for free.

It may only be of use to me, and it's pretty crude (there's no support for deleting attachments, for example) but it's been working nicely and has DRYed up my code in a satisfying way, so I thought I'd throw it out there. You can find it over on github.

(I'm not promising to keep supporting it, but it is used in an active project so chances are bug fixes will make it in. And of course, anyone is welcome to branch the project and twist it in their own ways)

Rails Plugins: attachment_fu

I’ve used Rick Olson‘s excellent acts_as_attachment on a number of projects and it’s saved me a huge amount of time that would have been spent worrying about how best to resize images, how to make sure uploaded files are properly written to storage, and other such boring details. So I’ve been noticing with interest increasing references to his new attachment_fu plugin, which is a complete rewrite of acts_as_attachment.

That interest was piqued as I skimmed this nice how-to on file attachment from Mike Clark (if you’re just looking for how to get started, go read that). It seems attachment_fu is almost entirely backwards compatible with acts_as_attachment (you just need to change your models to rename the ‘acts_as_attachment’ declaration ‘has_attachment’), but with a number of enhancements.

First up is the addition of pluggable ‘processors.’ Where acts_as_attachment relied on RMagick to manipulate images (useful things like creating thumbnails), attachment_fu supports ImageScience and MiniMagick, both of which are much lighter on resources than RMagick. And because each processor is implemented as its own module, you can easily add in any image processing library you can write a wrapper for.

So say you wanted to use a custom processor contained in the module Technoweenie::AttachmentFu::Processors::MyCustomProcessor, your model might look like:

class Avatar < ActiveRecord::Base
  has_attachment :content_type => :image, 
                 :processor => :my_custom, 
                 :max_size => 500.kilobytes,
                 :resize_to => '240x240>',
                 :thumbnails => { :thumb => '100x100>' }
 
  validates_as_attachment
end

Similarly, the storage code is also now pluggable. As Mike Clark explains in his tutorial, the first fruits of that is an S3 storage option, allowing all your uploaded files to be stored in your Amazon S3 account. But there’s no reason to stop there. To add your own storage option you’d just need a compatible module and to declare it just as you would a custom processor. For Technoweenie::AttachmentFu::Backends::MyCustomBackend the model would look like:

class Avatar < ActiveRecord::Base
  has_attachment :content_type => :image, 
                 :storage => :my_custom, 
                 :max_size => 500.kilobytes,
                 :resize_to => '240x240>',
                 :thumbnails => { :thumb => '100x100>' }
 
  validates_as_attachment
end

attachment_fu is only compatible with Rails 1.2+ so for those legacy projects still on older versions of Rails, it’s not an option. But for new projects, the ability to use other processors looks like a definite win, and the pluggable architecture is a nice bonus.