Ruby

Carrierwave AWS – copying files from one model to another

We have already a working code for copying Carrierwave files from one model to another, however, it is only working for file based storage. For Amazon S3 storage, it is quite not working. Here is our old code:

def import_images(ad, image_uuids)
  imgs = []
  transaction do
    asset_id = ad.asset_id
    image_uuids.each do |i|
      img = AssetImage.find_by(uuid: i, asset_id: asset_id)
      raise(Chuki::Forbidden, 'An asset image is not found') unless img
      begin
        imgs << img
        # Copy asset image to ad image
        create! ad: ad, image: img.image
      end if img
    end unless image_uuids.nil?
  end
  imgs
end

Every time it hits the import method, it throws this error on our staging server:

ArgumentError (wrong number of arguments (given 1, expected 0)):

carrierwave-aws (1.0.2) lib/carrierwave/storage/aws_file.rb:39:in `read'
fastimage (2.0.0) lib/fastimage.rb:327:in `block in fetch_using_read'

I immediately suspect it is about the Amazon AWS storage, so I tested it locally and indeed, the issue is about cloud storage.

The fix is quite simple and it has been documented in Carrierwave wiki. Below is our new code.

def import_images(ad, image_uuids)
  imgs = []
  transaction do
    asset_id = ad.asset_id
    image_uuids.each do |i|
      img = AssetImage.find_by(uuid: i, asset_id: asset_id)
      raise(Chuki::Forbidden, 'An asset image is not found') unless img
      begin
        imgs << img
        img.image.cache_stored_file!
        # Copy asset image to ad image
        create! ad: ad, image: img.image
      end if img
    end unless image_uuids.nil?
    CarrierWave.clean_cached_files!
  end
  imgs
end

That’s it. Enjoy and share!

Leave a reply

Your email address will not be published. Required fields are marked *