Papertrail and Carrierwave

前端 未结 3 1480
醉话见心
醉话见心 2021-02-15 01:41

I have a model that use both: Carrierwave for store photos, and PaperTrail for versioning.

I also configured Carrierwave for store diferent files when upda

3条回答
  •  清歌不尽
    2021-02-15 02:03

    Here is a bit updated version of monkeypatch from @rabusmar, I use it for rails 4.2.0 and paper_trail 4.0.0.beta2, in /config/initializers/paper_trail.rb.

    The second method override is required if you use optional object_changes column for versions. It works in a bit strange way for carrierwave + fog if you override filename in uploader, old value will be from cloud and new one from local filename, but in my case it's ok.

    Also I have not checked if it works correctly when you restore old version.

    module PaperTrail
      module Model
        module InstanceMethods
          private
    
          # override to keep only basename for carrierwave attributes in object hash
          def item_before_change
            previous = self.dup
            # `dup` clears timestamps so we add them back.
            all_timestamp_attributes.each do |column|
              if self.class.column_names.include?(column.to_s) and not send("#{column}_was").nil?
                previous[column] = send("#{column}_was")
              end
            end
            enums = previous.respond_to?(:defined_enums) ? previous.defined_enums : {}
            previous.tap do |prev|
              prev.id = id # `dup` clears the `id` so we add that back
              changed_attributes.select { |k,v| self.class.column_names.include?(k) }.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
                  before = enums[attr][before] if enums[attr]
                  prev[attr] = before
                end
              end
            end
          end
    
          # override to keep only basename for carrierwave attributes in object_changes hash
          def changes_for_paper_trail
            _changes = changes.delete_if { |k,v| !notably_changed.include?(k) }
            if PaperTrail.serialized_attributes?
              self.class.serialize_attribute_changes(_changes)
            end
            if defined?(CarrierWave::Uploader::Base)
              Hash[
                  _changes.to_hash.map do |k, values|
                    [k, values.map { |value| value.is_a?(CarrierWave::Uploader::Base) ? value.url && File.basename(value.url) : value }]
                  end
              ]
            else
              _changes.to_hash
            end
          end
    
        end
      end
    end
    

提交回复
热议问题