Cropping with Paperclip and the S3

15 Jul 2010

Paperclip is good. I pulled my hair out for several hours over this issue though. I had successfully implemented the custom cropping technique as demonstrated in railscast #182 but when I tried storing my images on the s3 I ran into a couple issues. The first was retrieving the image geometry. Instead of reading the geometry from the file I chose to read it out of the data we declare :styles option of the has_attached_file macro. This works for all but the original image - for that I use open-uri. It is probably pre-optimization but I didn't want to download every version just to find out their dimensions. My geometry methods look like this:

  require 'open-uri'
  
  def avatar_geometry(style=:large)
    return file_geometry if style == :original
    w, h = avatar.options[:styles][style].gsub("#","").split("x")
    Paperclip::Geometry.new(w, h)
  end
  def file_geometry
    @geometry ||= {}
    @geometry[avatar.url] ||= Paperclip::Geometry.from_file(open(avatar.url))
  end

My next issue manifested itself by not working and this error message appearing in my logs.

  paperclip No such file or directory @ blob.c/OpenBlob

I spent several hours searching for solutions but nothing came up. I started brute-force debugging where you start changing things just to see what makes a difference. It turns out I don't understand why the change I made that fixed the problem but for now I'm happy with a solution.

As I was messing with the transformation_command method of the Cropper processor I noticed that the super class implementation returns an array. The version from railscasts joins the array then substitutes the crop dimensions for our new dimensions. Returning a string works when the files are stored locally but I tried splitting it back into an array and it totally works. I don't know why!

  def transformation_command
    if crop_command
      cmd = crop_command + super.join(" ").sub(/ -crop \S+/, '')
      cmd.split(" ")
    else
      super
    end
  end