a work on process

Viewing posts tagged: attachment_fu

Announcing image_associations

20 August 2008 (8:06 am)

By James Stewart
Filed under: Announcements
Tagged: , , ,

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)

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

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.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]