Я использую Carrierwave с 3 отдельными моделями для загрузки фотографий на S3. Я сохранил настройки по умолчанию для загрузчика, который должен был хранить фотографии в корневой корзине S3. Затем я решил хранить их в подкаталогах в соответствии с названием модели, например /аватары, предметы/ и т. д., в зависимости от модели, из которой они были загружены...
Затем я заметил, что файлы с таким же именем перезаписываются, и когда я удалял запись модели, фотография не удалялась.
С тех пор я изменил store_dir из настройки, специфичной для загрузчика, следующим образом:
def store_dir
"items"
end
на общий, в котором хранится фотография под идентификатором модели (я использую mongo FYI):
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Вот в чем проблема. Я пытаюсь переместить все фотографии уже в S3 в соответствующий «каталог» в S3. Насколько я знаю, в S3 нет каталогов как таковых. У меня проблемы с задачей rake. Поскольку я изменил store_dir, Carrierwave ищет все фотографии, ранее загруженные в неправильный каталог.
namespace :pics do
desc "Fix directory location of pictures on s3"
task :item_update => :environment do
connection = Fog::Storage.new({
:provider => 'AWS',
:aws_access_key_id => 'XXXX',
:aws_secret_access_key => 'XXX'
})
directory = connection.directories.get("myapp-uploads-dev")
Recipe.all.each do |l|
if l.images.count > 0
l.items.each do |i|
if i.picture.path.to_s != ""
new_full_path = i.picture.path.to_s
filename = new_full_path.split('/')[-1].split('?')[0]
thumb_filename = "thumb_#{filename}"
original_file_path = "items/#{filename}"
puts "attempting to retrieve: #{original_file_path}"
original_thumb_file_path = "items/#{thumb_filename}"
photo = directory.files.get(original_file_path) rescue nil
if photo
puts "we found: #{original_file_path}"
photo.expires = 2.years.from_now.httpdate
photo.key = new_full_path
photo.save
thumb_photo = directory.files.get(original_thumb_file_path) rescue nil
if thumb_photo
puts "we found: #{original_thumb_file_path}"
thumb_photo.expires = 2.years.from_now.httpdate
thumb_photo.key = "/uploads/item/picture/#{i.id}/#{thumb_filename}"
thumb_photo.save
end
end
end
end
end
end
end
end
Итак, я просматриваю все рецепты, ищу элементы с фотографиями, определяю старый путь Carrierwave, пытаюсь обновить его новым на основе изменения store_dir. Я думал, что если бы я просто обновил photo.key с новым путем, это сработало бы, но это не так.
Что я делаю неправильно? Есть ли лучший способ выполнить вопрос здесь?
Вот что я сделал, чтобы это заработало...
namespace :pics do
desc "Fix directory location of pictures"
task :item_update => :environment do
connection = Fog::Storage.new({
:provider => 'AWS',
:aws_access_key_id => 'XXX',
:aws_secret_access_key => 'XXX'
})
bucket = "myapp-uploads-dev"
puts "Using bucket: #{bucket}"
Recipe.all.each do |l|
if l.images.count > 0
l.items.each do |i|
if i.picture.path.to_s != ""
new_full_path = i.picture.path.to_s
filename = new_full_path.split('/')[-1].split('?')[0]
thumb_filename = "thumb_#{filename}"
original_file_path = "items/#{filename}"
original_thumb_file_path = "items/#{thumb_filename}"
puts "attempting to retrieve: #{original_file_path}"
# copy original item
begin
connection.copy_object(bucket, original_file_path, bucket, new_full_path, 'x-amz-acl' => 'public-read')
puts "we just copied: #{original_file_path}"
rescue
puts "couldn't find: #{original_file_path}"
end
# copy thumb
begin
connection.copy_object(bucket, original_thumb_file_path, bucket, "uploads/item/picture/#{i.id}/#{thumb_filename}", 'x-amz-acl' => 'public-read')
puts "we just copied: #{original_thumb_file_path}"
rescue
puts "couldn't find thumb: #{original_thumb_file_path}"
end
end
end
end
end
end
end
Возможно, не самая красивая вещь в мире, но это сработало.