diff --git a/app/models/concerns/has_migrating_file.rb b/app/models/concerns/has_migrating_file.rb new file mode 100644 index 0000000000..d82528f38c --- /dev/null +++ b/app/models/concerns/has_migrating_file.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module HasMigratingFile + extend ActiveSupport::Concern + + class_methods do + def has_one_migrating(name, paperclip_options = {}) + # Active Storage declaration + has_one_attached name + + # Backup Active Storage methods before they get overridden by Paperclip. + alias_method "active_storage_#{name}", name + alias_method "active_storage_#{name}=", "#{name}=" + + # Paperclip declaration + # + # This will define the `name` and `name=` methods as well. + has_attached_file name, paperclip_options + + # Paperclip callback to duplicate file with Active Storage + # + # We store files with Paperclip *and* Active Storage while we migrate + # old Paperclip files to Active Storage. This enables availability + # during the migration. + after_post_process do + if public_send(name).errors.blank? + file = File.open(processed_local_file_path) + attach_file(name, file) + end + end + end + end + + def attach_file(name, io) + attachable = { + io: io, + filename: public_send("#{name}_file_name"), + content_type: public_send("#{name}_content_type"), + identify: false, + } + public_send("active_storage_#{name}=", attachable) + end + + private + + def processed_local_file_path(name) + attachment = public_send(name) + + temporary = attachment.queued_for_write[:original] + + if temporary&.path.present? + temporary.path + else + attachment.path + end + end +end diff --git a/app/models/spree/image.rb b/app/models/spree/image.rb index 3d835de7b2..996067ec6f 100644 --- a/app/models/spree/image.rb +++ b/app/models/spree/image.rb @@ -4,27 +4,18 @@ require 'spree/core/s3_support' module Spree class Image < Asset + include HasMigratingFile + validates_attachment_presence :attachment validate :no_attachment_errors - # Active Storage declaration - has_one_attached :attachment - - # Backup Active Storage methods before they get overridden by Paperclip. - alias_method :active_storage_attachment, :attachment - alias_method :active_storage_attachment=, :attachment= - - # Paperclip declaration - # - # This will define the `name` and `name=` methods as well. - # # This is where the styles are used in the app: # - mini: used in the BackOffice: Bulk Product Edit page and Order Cycle edit page # - small: used in the FrontOffice: Product List page # - product: used in the BackOffice: Product Image upload modal in the Bulk Product Edit page # and Product image edit page # - large: used in the FrontOffice: product modal - has_attached_file :attachment, + has_one_migrating :attachment, styles: { mini: "48x48#", small: "227x227#", product: "240x240>", large: "600x600>" }, default_style: :product, @@ -32,18 +23,6 @@ module Spree path: ':rails_root/public/spree/products/:id/:style/:basename.:extension', convert_options: { all: '-strip -auto-orient -colorspace sRGB' } - after_post_process do - if attachment.errors.blank? - attachable = { - io: File.open(local_filename_of_original), - filename: attachment_file_name, - content_type: attachment_content_type, - identify: false, - } - self.active_storage_attachment = attachable - end - end - # save the w,h of the original image (from which others can be calculated) # we need to look at the write-queue for images which have not been saved yet after_post_process :find_dimensions