Attachment_fu is a great plugin by Rick Olsen (a.k.a. techno-weenie). I use this plugin for one of the sites I maintain. I recently ran into a situation where I needed to regenerate the thumbnails for all the uploaded images. Attachment_fu provides no built-in support for this, so I had to get creative. A quick search on Google revealed a post by Michael D. Ivey that seemed like a reasonable thing to do, but was not sufficient by itself. So in this blog, I plan to cover the steps I took to automate the regeneration of thumbnails when you are using attachment_fu.
So the jist of the problem was that I wanted attachment_fu to generate an additional thumbnail when saving files. The easy route would have been to forget about regenerating anything and consider it an acceptable loss to not have this additional thumbnail with all the previously uploaded images. However, that would have caused some cosmetic damage to the site. Thus, regeneration was needed.
Original has_attachment configuration
class GalleryImage < ActiveRecord::Base
[...]
has_attachment :storage => :file_system,
:path_prefix => 'public/gallery_images',
:thumbnails => { :archive => '119>x88>', :thumb => '64>x48>', :small => '340>x255>', :medium => '640>x480>', :large => '1024>x768>' },
:content_type => :image,
:max_size => 5.megabytes
[...]
end
New has_attachment configuration
class GalleryImage < ActiveRecord::Base
[...]
has_attachment :storage => :file_system,
:path_prefix => 'public/gallery_images',
:thumbnails => { :archive => '119>x88>', :thumb => '64>x48>', :small => '340>x255>', :medium => '640>x480>', :large => '1024>x768>', :square => [50,50] },
:content_type => :image,
:max_size => 5.megabytes
[...]
end
Note the addition of the :square => [50,50]. That's the new guy. It's probably worth noting that I wanted to generate a thumbnail that was perfectly square to maintain a cosmetic consistently to the page. I actually created a patch for attachment_fu to do this in case anyone else might find it useful. Here ya go.
square_thumbnails_for_attachment_fu.patch
## This patch enables the use of square thumbnails.
--- a/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
+++ b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
@@ -41,7 +41,7 @@ module Technoweenie # :nodoc:
size = size.first if size.is_a?(Array) && size.length == 1 && !size.first.is_a?(Fixnum)
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
size = [size, size] if size.is_a?(Fixnum)
- img.thumbnail!(*size)
+ size[0] == size[1] ? img.crop_resized!(*size) : img.thumbnail!(*size)
else
img.change_geometry(size.to_s) { |cols, rows, image| image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows) }
end
Note: Once patched, it will create square thumbnails when you provide a thumbnail parameter such like :my_squre_thumb => [50,50]. If the array contains the same parameters, attachment_fu will make a square thumbnail and not squeeze/squish it.
As I mentioned, I needed to patch attachment_fu to do my own thing. This was because one of the problems I quickly ran into was that the method used to determine if something was "thumbnailable" checked for the presence of a "parent id". Since I had pre-existing images, they all had "parent ids" and thus I would just receive an error that said the following:
Can't create a thumbnail if the content type is not an image or there is no parent_id column
Alright, so after some investigation, I found out that it had to do with the thumbnailable? method. Since I wanted a solution that was automated, I decided to create a rake task. This rake task would apply a patch to attachment_fu when executed, regenerate all the thumbnails, and then reverse the patch.
regenerate_thumbnails_runtime.patch
# Diables the check for a nil parent_id.
+++ ../vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb
--- ../vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb
@@ -220,7 +220,7 @@ module Technoweenie # :nodoc:
# Returns true/false if an attachment is thumbnailable. A thumbnailable attachment has an image content type and the parent_id attri
def thumbnailable?
- image? && respond_to?(:parent_id) && parent_id.nil?
+ image? && respond_to?(:parent_id) #&& parent_id.nil?
end
# Returns the class used to create new thumbnails for this attachment.
Alright, so now that I had a patch, I needed a rake task. I decided to actually create two rake tasks. One for my local development environment and one for my production server.
regenerate_thumbs.rake
namespace :regenerate_thumbs do
desc "Regenerate thumbnails for development environment"
task :development do
puts "Regenerating the thumbnails..."
# Patch attachment_fu
system "patch -p1 --no-backup-if-mismatch #{Rails.root}/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb < #{Rails.root}/lib/patches/regenerate_thumbnails_runtime.patch"
# Regenerate thumbnails
system "script/runner -e development 'Administration.regenerate_gallery_thumbnails'"
# Unpatch attachment_fu
system "patch -p1 -R --no-backup-if-mismatch #{Rails.root}/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb < #{Rails.root}/lib/patches/regenerate_thumbnails_runtime.patch"
end
desc "Regenerate thumbnails for production environment"
task :production do
puts "Regenerating the thumbnails..."
# Patch attachment_fu
system "patch -p1 --no-backup-if-mismatch #{Rails.root}/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb < #{Rails.root}/lib/patches/regenerate_thumbnails_runtime.patch"
# Regenerate thumbnails
system "script/runner -e production 'Administration.regenerate_gallery_thumbnails'"
# Unpatch attachment_fu
system "patch -p1 -R --no-backup-if-mismatch #{Rails.root}/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb < #{Rails.root}/lib/patches/regenerate_thumbnails_runtime.patch"
end
end
Alright, now we've gotten as far as creating a runtime patch and a rake task. One thing that you'll note in the rake task is that I use script/runner to execute a method in my Administration model. So to explain, I have an Administration model where I put miscellaneous tasks like session cleanup, thumbnail regeneration, and other admin-related tasks. You can do something similar or create the self.regenerate_gallery_thumbnails method below in an existing model.
app/models/Administration.rb
class Administration < ActiveRecord::Base
def self.regenerate_gallery_thumbnails
GalleryImage.find(:all).each do |p|
next if p.gallery_id.nil?
puts "Regenerating thumbnails for #{p.filename}"
begin
temp_file = p.create_temp_file
rescue
puts "Failed to create temp file for #{p.id}"
nil
end
p.attachment_options[:thumbnails].each { |suffix, size|
begin
p.create_or_update_thumbnail(temp_file, suffix, *size)
rescue
puts "Failed to process #{p.id}"
nil
end
}
end
end
end
Alright, that about sums it up. Now all I had to do is cross my fingers and make sure I had a backup of the database and images. Then it was just a matter of running one of the following commands, depending on my desired environment:
rake regenerate_thumbs:development
or
rake regenerate_thumbs:production
Given that this took me a few hours to figure out, I decided to post on here in case it might help someone else out. Maybe someday Rick will introduce this functionality into a version of attachment_fu, keep your fingers crossed and good luck.


For me the problem is just the opposite: attachment_fu always regenerates the thumbnails after each update of my Photo models, even if you didn’t upload a new file, say, you just updated its title.
So I don’t understand why you need to do all that… just do a model.save and you’re done with thumbnails regeneration. At least, on the latest versions of attachment_fu.