Rotating Paperclip Image Attachments in Rails

With users uploading personal photos, especially ones coming their phones that capture landscape photos in portrait mode and vice versa, one of the things I wanted to integrate into Black Book Singles is the ability to rotate photos. Since I’m using the Paperclip gem, this should be relatively easy to achieve through a custom attachment processor.

Doing a precursory search resulted in a bit of helpful code to get me started. Thanks to tekn0t for sharing his example in this gist.

Unfortunately, I came to the conclusion that this example has three main issues:

It doesn’t follow Paperclip convention of passing a set of option key/value pairs into the Processor class to enable the processing.

It assumes any class that implements it also implements both rotating? and rotation methods or attributes, with no flexibility on the naming.

The base class of the implemented Rotator class is Thumbnail. Because Thumbnail is included by default when the geometry option is used, this means the geometry commands will unnecessarily be executed twice.

With these things in mind, I set out to rewrite the example code into a more robust implementation.

First, we’re going to need an attribute on our model that keeps track of the current angle of rotation. This is necessary so that future rotations will be based upon the current angle in degrees. To do this, create a migration that adds an integer column named rotation to whichever Paperclip model you’re working with.

Next, we’ll want a simple way to update the rotation value on a model. Since Paperclip needs to be explicitly told when to reprocess an image, we’ll need to tell it to do so whenever this value changes. Also, keep in mind that basic math tells us that the only degrees we should worry about are between 0-360, meaning we can perform a simple modulus operation on our rotation to keep it in this range.

So far, our code has’t done anything to tell Paperclip what to do. The first step in notifying Paperclip is to update the hash passed into has_attached_file. Notably, we’ll want to include :rotator (which will be the name of our processor class) into the array of processors. Also, we’ll need to pass a :rotation key/value pair in with each attachment style we wish to process as such. Since this call is being made at the model level, we can’t simply use self.rotation to access the value of the record’s rotation angle. Fortunately, Paperclip allows us to use a lambda function to return a styles hash, which includes the Attachment object. Knowing this, we can access this current record’s rotation via attachment.instance.rotation.

Finally, now that we’re passing the rotation value to Paperclip, we need to create the processor to handle it. Much of the basis of this code is taken from the Thumbnail processor included with Paperclip, which I won’t be delving into. The main thing to pay attention to is any code pertaining to the rotation attribute being set and used, most notably in the transformation_command method.

If I remove the “:processors=>[:rotator]” line, upload the file, then replace the line, then set the rotation to something > 0, then it works fine. If I then set the rotation back to 0 i get the same error message.

Hi Peter. The version I was using when I wrote this article was Paperclip 2.4.5. I haven’t followed the changes between 2.4.5 and 3.0.4 to know whether that would have a drastic effect on how processors are implemented, unfortunately.

Hey Matt, i’m having some problems, when is trying to upload the images with s3 it shows a bad uri error because is trying to get from http, i put in the s3_protocol https so i don’t know what could be happening… can you help me with this??? thanks

Hi Damien. It’s hard to tell without having a sample project and the full code, but a few things I would look at (in order) are:

* Where is :s3_escaped_path_url defined? How is that getting interpreted in the :url option?
* What is AMAZON_S3_ROOT_PATH defined as?
* What version of Paperclip are you using, and when was the :s3_protocol option introduced?