Ruby on rails 3 如何使用CarrierWave重新组织现有文件夹层次结构?

Ruby on rails 3 如何使用CarrierWave重新组织现有文件夹层次结构?,ruby-on-rails-3,carrierwave,reorganize,Ruby On Rails 3,Carrierwave,Reorganize,我正在尝试使用CarrierWave重新组织文件夹结构,在S3存储桶周围移动文件 我来到了一个现有的Rails应用程序,其中一个类的所有图像都被上传到一个名为/uploads的文件夹中。这会导致问题,如果两个用户上载具有相同文件名的不同图像,则第二个图像将覆盖第一个图像。为了解决这个问题,我想根据ActiveRecord对象实例重新组织文件夹,将每个图像放在自己的目录中。我们使用CarrierWave管理文件上传 旧的上载程序代码具有以下方法: def store_dir "uploads"

我正在尝试使用
CarrierWave
重新组织文件夹结构,在S3存储桶周围移动文件

我来到了一个现有的Rails应用程序,其中一个类的所有图像都被上传到一个名为
/uploads
的文件夹中。这会导致问题,如果两个用户上载具有相同文件名的不同图像,则第二个图像将覆盖第一个图像。为了解决这个问题,我想根据
ActiveRecord
对象实例重新组织文件夹,将每个图像放在自己的目录中。我们使用
CarrierWave
管理文件上传

旧的上载程序代码具有以下方法:

def store_dir
  "uploads"
end
我修改了该方法以反映我的新文件存储方案:

def store_dir
  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
这对新图像非常有效,但会破坏旧图像的url。当我更改模型时,现有图像报告其URL立即位于新文件夹中,而图像文件仍存储在
/uploads

> object.logo.store_dir
=> "uploads/object/logo/133"
这是不对的。此对象应在
/uploads
中报告其徽标

> object.logo.store_dir
=> "uploads/object/logo/133"
我的解决方案是编写一个脚本来移动图像文件,但我还没有在CarrierWave中找到移动文件的正确方法。我的脚本如下所示:

MyClass.all.each |image|
  filename = file.name #This method exists in my uploader, returns the file name
  #Move the file from "/uploads" to "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end 
MyClass.all.each do |image|
  image.image.cache! #create a local cache so that store! has something to store
  image.image.store!
end

在脚本的第三行中,我应该如何将文件移动到新位置?

警告:这是未经测试的,因此在测试之前,请不要在生产中使用它

事情是这样的,一旦你更改了“store_dir”的内容,你所有的旧上传就会丢失。你已经知道了。直接与S3交互似乎是解决这个问题最明显的方法,因为carrierwave没有移动函数

一件可能有效的事情是重新“存储”您的上传,并在“before:store”回调中更改“store_dir”路径

在您的上传程序中:

#Use the old uploads directory so carriewave knows where the original upload is
def store_dir
  'uploads'
end

before :store, :swap_out_store_dir

def swap_out_store_dir
  self.class_eval do
    def store_dir
      "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end
  end
end
然后运行如下脚本:

MyClass.all.each |image|
  filename = file.name #This method exists in my uploader, returns the file name
  #Move the file from "/uploads" to "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end 
MyClass.all.each do |image|
  image.image.cache! #create a local cache so that store! has something to store
  image.image.store!
end
之后,请确认文件已复制到正确的位置。然后,您必须删除旧的上载文件。此外,请删除上面的一次性使用上载程序代码,并将其替换为新的存储目录路径:

def store_dir
  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id} "
end

我还没有测试过,所以我不能保证它会工作。请先使用测试数据查看它是否有效,如果您取得了任何成功,请在此处发表评论。

您是否找到了解决方案?我也有同样的问题。这可能不适用于你,除非你使用fog,但这是我找到的最好的解决方案,我一直在努力寻找:对我来说工作完美。一眨眼间就移动了数千个文件。干杯。我遇到了替换脚本的问题。但您可以在不使用carrierwave的情况下替换生产中的文件夹和文件。