Papertrail and Carrierwave

Adding @beardedd's comment as an answer because I think this is a better way to handle the problem.

Name your database columns something like picture_filename and then in your model mount the uploader using:

class User < ActiveRecord::Base has_paper_trail mount_uploader :picture, PictureUploader, mount_on: :picture_filename end

You still use the user.picture.url attribute to access your model but PaperTrail will store revisions under picture_filename.


You can override item_before_change on your versioned model so you don't call the uploader accesor directly and use write_attribute instead. Alternatively, since you might want to do that for several models, you can monkey-patch the method directly, like this:

module PaperTrail
  module Model
    module InstanceMethods
      private
        def item_before_change
          previous = self.dup
          # `dup` clears timestamps so we add them back.
          all_timestamp_attributes.each do |column|
            previous[column] = send(column) if respond_to?(column) && !send(column).nil?
          end
          previous.tap do |prev|
            prev.id = id
            changed_attributes.each do |attr, before|
              if defined?(CarrierWave::Uploader::Base) && before.is_a?(CarrierWave::Uploader::Base)
                prev.send(:write_attribute, attr, before.url && File.basename(before.url))
              else
                prev[attr] = before
              end
            end
          end
        end
    end
  end
end

Not sure if it's the best solution, but it seems to work.