Как я могу реорганизовать существующую иерархию папок с помощью CarrierWave?

Я пытаюсь перемещать файлы по корзине S3, используя CarrierWave для реорганизации структуры папок.

Я пришел к существующему приложению 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.

Мое решение состоит в том, чтобы написать сценарий для перемещения файлов изображений, но я не нашел в 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 

Что я должен сделать в третьей строке моего скрипта, чтобы переместить файл в новое место?


person Omar    schedule 04.04.2013    source источник
comment
Вы когда-нибудь находили решение? У меня такая же проблема.   -  person Tim Coulter    schedule 30.08.2013
comment
Это, возможно, неприменимо к вам, если вы не используете туман, но это лучшее решение, которое я нашел, и я довольно усердно искал: stackoverflow.com /вопросы/19038733/   -  person Nick Gottlieb    schedule 20.12.2013


Ответы (1)


ВНИМАНИЕ: Это не тестировалось, поэтому, пожалуйста, не используйте его в продакшене, пока не протестируете.

Дело в том, что как только вы измените содержимое store_dir, все ваши старые загрузки исчезнут. Вы это уже знаете. Взаимодействие с S3 напрямую кажется наиболее очевидным способом решения этой проблемы, поскольку у несущей волны нет функции перемещения.

Одна вещь, которая может сработать, - это повторно «сохранить» ваши загрузки и изменить путь «store_dir» в обратном вызове «before: store».

В вашем загрузчике:

#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 do |image|
  image.image.cache! #create a local cache so that store! has something to store
  image.image.store!
end

После этого убедитесь, что файлы были скопированы в правильные места. Затем вам придется удалить старые файлы загрузки. Кроме того, удалите приведенный выше одноразовый код загрузчика и замените его новым путем store_dir:

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

Я не проверял это, поэтому не могу гарантировать, что это сработает. Пожалуйста, сначала используйте тестовые данные, чтобы увидеть, работает ли это, и прокомментируйте здесь, если вы добились успеха.

person cgat    schedule 02.01.2014
comment
Работал идеально для меня. Просто переместил тысячи файлов в одно мгновение. Ваше здоровье. - person Pete Hamilton; 24.01.2014
comment
У меня была проблема с replace_script. Но вы можете заменить папки и файлы на производство без носителя. - person Pavel Kalashnikov; 20.08.2015