保存我的ActiveRecord模型会删除我的CarrierWave图像版本

时间:2013-01-22 15:38:41

标签: ruby-on-rails carrierwave rails-activerecord

每当我使用已安装的上传器保存模型时,只要我保存它就会删除版本(并且看起来好像在正常上传图像时甚至没有创建版本)。请注意,它曾经在几天/几周之前正常工作(我没有注意到确切的时间,尽管可能已经发生了转移到Rails 3.2.11。我之前是3.2.8。)

我的模型定义如下:

class Profile < ActiveRecord::Base
  attr_accessible :profile_picture
  mount_uploader :profile_picture, ProfilePictureUploader
  ...
end

我的ProfilePictureUploader

class ProfilePictureUploader < BaseUploader
  process :resize_to_fill => [248, 248]

  version :tiny do
    process :resize_to_fill => [34, 34]
    def full_filename(for_file = model.photo.file)
      "#{model.to_s.parameterize}_tiny.jpg"
    end
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  def filename
    # John Snow -> john-snow-20120913162935.jpg
    # ACME inc. -> acme-inc-20120913162935.png
    "#{model.to_s.parameterize}-#{Time.now.strftime("%Y%m%d%H%M%S")}#{File.extname(original_filename)}" if original_filename
  end
end

最后我的BaseUploader

class BaseUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

  # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
  include Sprockets::Helpers::RailsHelper
  include Sprockets::Helpers::IsolatedHelper

  # Override the directory where uploaded files will be stored.
  def store_dir
    "system/uploads/#{model.class.to_s.underscore}/#{model.id}"
  end

  # Override the filename of the uploaded files:
  def filename
    "#{mounted_as}#{File.extname(original_filename)}" if original_filename
  end
end

我在生产中使用文件存储开发和雾存储,但问题出现在两个环境中,所以让我们假设它使用文件存储。

这是我的典型情景:

  • 我将图片上传到个人资料,只创建了标准图片(例如:mbillard-20130122102833.jpg)。
  • 我在个人资料图片上调用了recreate_versions!,标准图片和小版本都被创建了(由于我的特定命名方案,标准被重新创建,我很好)。
  • 我保存了我的模型,文件夹(system/uploads/profile/1/)中的所有内容都被删除,但文件名为profile_picture的图片除外。

我使用了carrierwave 0.8.0。我相信它与保存触发器有关,但无法通过查看代码来解决它。

(我还开了一个GitHub issue并行)

1 个答案:

答案 0 :(得分:0)

我终于明白了。基本上,似乎remove_previously_stored_#{column}中的mount.rb方法删除了我新创建的版本,因为它们与以前的版本具有相同的名称。

我修改了我的小版本文件名以包含时间戳(因此它与前一个小版本的文件名不同):

version :tiny do
  process :resize_to_fill => [34, 34]
  def full_filename(for_file = model.photo.file)
    "#{model.to_s.parameterize}_#{timestamp}_tiny.jpg"
  end
end

我将filename逻辑简化为简单定义带有时间戳的文件名:

# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
def filename
  # John Snow -> john-snow-20120913162935.jpg
  # ACME inc. -> acme-inc-20120913162935.png

  "#{model.to_s.parameterize}-#{timestamp}#{File.extname(original_filename)}" if original_filename.present?
end

我的时间戳功能要么从文件名中提取时间戳,要么在重新创建版本或上传新文件时生成新的时间戳(当存在original_filename时):

protected

def timestamp
  if original_filename.blank?
    match_data = /^.+-(\d{14})\.\D{3,4}$/.match(File.basename(model.read_attribute(mounted_as)))

    return match_data[1] if match_data
  end

  var = :"@#{mounted_as}_timestamp"
  model.instance_variable_get(var) || model.instance_variable_set(var, Time.now.strftime("%Y%m%d%H%M%S"))
end

请注意,之前的时间戳可以存储在我的模型的属性中,但这对我有用。

现在唯一让我烦恼的是我必须保存我的模型才能在重新创建版本时删除以前的文件。

model.recreate_versions! # recreates versions but leaves the previous files there
model.save # removes the previous files

您可以在GitHub issue上看到我的整个思考过程。