Papertrail和Carrierwave

eve*_*ans 9 ruby-on-rails ruby-on-rails-3 carrierwave paper-trail-gem

我有一个使用两者的模型:Carrierwave用于商店照片和PaperTrail版本控制.

我还在更新时配置了Carrierwave用于存储不同的文件(那是因为我想对照片进行版本控制) config.remove_previously_stored_files_after_update = false

问题是PaperTrail尝试从照片(CarrierWave Uploader)存储整个Ruby对象而不是简单的字符串(这将是它的url)

(版本表,列对象)

---
first_name: Foo
last_name: Bar
photo: !ruby/object:PhotoUploader
  model: !ruby/object:Bla
    attributes:
      id: 2
      first_name: Foo1
      segundo_nombre: 'Bar1'
      ........
Run Code Online (Sandbox Code Playgroud)

如何修复此问题以在照片版本中存储简单的字符串?

rab*_*mar 10

您可以覆盖item_before_change版本化的模型,这样就不会直接调用上传器访问者write_attribute而是使用它.或者,既然您可能希望为多个模型执行此操作,则可以直接对该方法进行修补,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

不确定它是否是最佳解决方案,但似乎有效.

  • 作为替代方案,我发现最简单的方法就是安装在不同的属性上,这样可以避免问题与纸质跟踪,不需要猴子修补 (3认同)

Ger*_*haw 6

添加@ beardedd的评论作为答案,因为我认为这是处理问题的更好方法.

将数据库列命名为picture_filename,然后在模型中使用以下命令安装上传器:

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

您仍然使用该user.picture.url属性访问您的模型,但PaperTrail将存储修订版picture_filename.