As SNGTRKR is still in its infancy, we find ourselves tweaking the image sizes our models have on a semi-regular basis. Fortunately Paperclip makes that a doddle; just a one line change to the model definition and away we go.

Now all thats left to address is the missing copies of this new image size in production. We have well over 10,000 records with large images associated with them in the database, so the naïve approach of reprocessing every model isn’t going to suffice here. In theory though we still have a weapon in our arsenal; Paperclip provides the paperclip:refresh:missing_styles rake task, which will look for a YAML file in your project that stores the previously generated styles.

Unfortunately, that’s as far as that file goes. It does not store per record granularity, so if that rake should bail at some point through your 10,000+ records, well, start again! Haha, screw that. This actual happened to us, for reasons I am still not 100% sure on, but I can only assume it was an S3 connection issue or similar. To solve it, I wrote my own method to do roughly the same as what Paperclip does, but in a slightly more intelligent way; we check whether a potentially missing image exists for each record of a given ActiveRecord model (this is a Rails-centric solution) by actually trying to open the URL the image would be at.

Not only can this be stopped and effectively resumed (that is it will never reprocess an image that has already been processed), but if an error is raised during the reprocessing step, it will entirely delete the image from the record, as we assume there has been some kind of corruption between the record and its S3 files.

 # admin_tools.rb

class AdminTools

  # For reprocessing Paperclip images, when certain styles are missing.
  # Had to do it myself because their rake seems to crash for unknown reasons.
  # This also has the advantage of checking if the file exists rather than just assuming all don't.
  # We assume if the large image is missing, we need to reprocess this item.
  # AdminTools.reprocess_missing_images Class, :image_size
  def self.reprocess_missing_images klass, missing_style
    klass.find_each do |inst|
      rep = false
      puts "START #{inst.id}"
      unless inst.image.present?
        next
      end
      image = inst.image(missing_style)
      begin
        actual = open(image)
      rescue
        rep = true
      end
      if actual.is_a?(StringIO) or !rep
        puts "SKIP #{inst.id}"
        next
      end

      puts "REPROCESS #{inst.id}"

      begin
        inst.image.reprocess!(missing_style)
      rescue
        # We assume that for images that fail the record is in some way corrupt,
        # you may not want to do this.
        inst.image.destroy
      end
    end
  end

end

Feel free to use it, and if you make any improvements, please leave a comment!