Maxim Fedotov
Maxim Fedotov

Reputation: 1357

Carrierwave doesn't recreate versions after the model update

I've introduced a new version on my Carrierwave Uploader. When I create a new Event it creates both versions correctly. But when I update it, only the file I attached gets uploaded, but versions do not get recreated.

I am using CarrierWave 1.2.2, and looking at the changelog, it doesn't seem to have been a bug that got fixed in the newer versions

class CoverUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  if Rails.env.development? || Rails.env.test?
    storage :file
  elsif Rails.env.production?
    storage :fog
  end

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    if ENV['HEROKU_APP_NAME'].to_s.include?('-pr-')
      "review_apps/#{model.class.to_s.underscore}/#{model.id}"
    else
      "#{Rails.env}/#{model.class.to_s.underscore}/#{model.id}"
    end
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  def default_url(*args)
    ActionController::Base.helpers.asset_path('test.jpg')
  end

  # Create different versions of your uploaded files:
  version :optimised do
    process convert: 'webp'
    process :set_content_type_to_webp

    def full_filename(_for_file = model.cover.file)
      "cover_#{model.id}.webp"
    end

    def exists?
      file&.exists?
    end
  end

  def extension_blacklist
    %w(webp)
  end

  private

  # Required to actually force Amazon S3 to treat it like an image
  def set_content_type_to_webp
    file.instance_variable_set(:@content_type, 'image/webp')
  end
end

Upvotes: 4

Views: 1854

Answers (2)

Maxim Fedotov
Maxim Fedotov

Reputation: 1357

@ogelacinyc was partly correct when he found the bug in full_filename. I went back to test normal functionality with creating another version, with a simple dimension change. I could then see that update would recreate the versions by itself, just like I expected.

That made me think that maybe there is something wrong with my version :optimised block. So after commenting one by one, I found that full_filename was the culprit. It could have been model.cover.file failing silently, but I think it was model.id, as can be seen in the description for filename method in Carrierwave

So instead, I grab the filename directly, extract extension and substitute it with webp:

  def full_filename(for_file = model.file_name.file)
    extension = File.extname(for_file)
    "cover_#{for_file.sub(extension, '.webp')}"
  end

Which works without problems!

Upvotes: 2

danielricecodes
danielricecodes

Reputation: 3586

You need to add an after_save callback to Event and then call recreate_versions! on your mounted uploader.

Assuming you have an Event model with the following, this would solve your problem.

class Event < ApplicationRecord
  mount_uploader :cover_image, CoverUploader
  after_save :recreate_versions!
  delegate :recreate_versions!, to: :cover_image, allow_nil: true
end

See CarrierWave's README also.

Upvotes: 0

Related Questions