Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Paperclip Adapter #5100

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/lib/generators/solidus/install/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def install_file_attachment
rake 'active_storage:install'
else
say_status :assets, "Paperclip", :green
gsub_file 'config/initializers/spree.rb', "::ActiveStorageAttachment", "::PaperclipAttachment"
rake "solidus:paperclip_adapter:install"
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

require 'rails/generators'

module Solidus
# @private
module PaperclipAdapter
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path('templates', __dir__)

class_option :set_preferences,
type: :boolean,
default: true,
banner: 'Wheter or not to set the preferences in the initializer for the attachment adapters'

class_option :app_directory,
type: :string,
default: Rails.root,
hide: true

class_option :initializer_directory,
type: :string,
default: 'config/initializers/',
hide: true

class_option :initializer_basename,
type: :string,
default: 'spree',
banner: 'The name of the initializer containing the attachment adapters settings'

class_option :app_name,
type: :string,
default: Rails.application.class.module_parent.name,
banner: 'The name of the host application'

def copy_templates
say_status :template, "Paperclip Adapters", :green
template 'app/models/spree/image/paperclip_attachment.rb.tt',
File.join(options[:app_directory], "app/models/#{options[:app_name].underscore}/image/paperclip_attachment.rb")

template 'app/models/spree/taxon/paperclip_attachment.rb.tt',
File.join(options[:app_directory], "app/models/#{options[:app_name].underscore}/taxon/paperclip_attachment.rb")
end

def replace_paperclip_adapter
return unless options[:set_preferences] == true

say_status :preference, "Custom Paperclip Adapters", :green

gsub_file File.join(options[:app_directory], options[:initializer_directory], "#{options[:initializer_basename]}.rb"),
"Spree::Image::PaperclipAttachment",
"#{options[:app_name]}::Image::PaperclipAttachment"

gsub_file File.join(options[:app_directory], options[:initializer_directory], "#{options[:initializer_basename]}.rb"),
"Spree::Taxon::PaperclipAttachment",
"#{options[:app_name]}::Taxon::PaperclipAttachment"
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

module <%= options[:app_name] %>
module Image
module PaperclipAttachment
extend ActiveSupport::Concern

included do
validate :no_attachment_errors

has_attached_file :attachment,
styles: Spree::Config.product_image_styles,
default_style: Spree::Config.product_image_style_default,
default_url: 'noimage/:style.png',
url: '/spree/products/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/products/:id/:style/:basename.:extension',
convert_options: { all: '-strip -auto-orient -colorspace sRGB' }
validates_attachment :attachment,
presence: true,
content_type: { content_type: Spree::Config.allowed_image_mime_types }

# 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, if: :valid?
end

def url(size)
attachment.url(size)
end

def filename
attachment_file_name
end

def attachment_present?
attachment.present?
end

def find_dimensions
temporary = attachment.queued_for_write[:original]
filename = temporary.path unless temporary.nil?
filename = attachment.path if filename.blank?
geometry = Paperclip::Geometry.from_file(filename)
self.attachment_width = geometry.width
self.attachment_height = geometry.height
end

# if there are errors from the plugin, then add a more meaningful message
def no_attachment_errors
unless attachment.errors.empty?
# uncomment this to get rid of the less-than-useful interim messages
# errors.clear
errors.add :attachment, "Paperclip returned errors for file '#{attachment_file_name}' - check ImageMagick installation or image source file."
false
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module <%= options[:app_name] %>
module Taxon
module PaperclipAttachment
extend ActiveSupport::Concern

included do
has_attached_file :icon,
styles: Spree::Config.taxon_image_styles,
default_style: Spree::Config.taxon_image_style_default,
url: '/spree/taxons/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/taxons/:id/:style/:basename.:extension',
default_url: '/assets/default_taxon.png'

validates_attachment :icon,
content_type: { content_type: Spree::Config.allowed_image_mime_types }
end

def icon_present?
icon.present?
end

def destroy_attachment(definition)
return false unless respond_to?(definition)

attached_file = send(definition)
return false unless attached_file.exists?

attached_file.destroy
save
end
end
end
end
25 changes: 25 additions & 0 deletions core/lib/spree/app_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,18 @@ def payment_canceller
# @return [Module] a module that can be included into Spree::Image to allow attachments
# Enumerable of images adhering to the present_image_class interface
class_name_attribute :image_attachment_module, default: "Spree::Image::ActiveStorageAttachment"
def image_attachment_module=(value)
if value == 'Spree::Image::PaperclipAttachment'
Spree::Deprecation.warn <<~MSG
Solidus will remove built-in support for Paperclip as image adapter in the next major version.
Please, use the provided generator to incorporate the current Paperclip adapter in your application with:

bin/rails g solidus:paperclip_adapter:install
MSG
end

preferences[:image_attachment_module] = value
end

# @!attribute [rw] allowed_image_mime_types
#
Expand Down Expand Up @@ -558,6 +570,19 @@ def payment_canceller
# @return [Module] a module that can be included into Spree::Taxon to allow attachments
# Enumerable of taxons adhering to the present_taxon_class interface
class_name_attribute :taxon_attachment_module, default: "Spree::Taxon::ActiveStorageAttachment"
def taxon_attachment_module=(value)
if value == 'Spree::Taxon::PaperclipAttachment'
Spree::Deprecation.warn <<~MSG
Solidus will remove built-in support for Paperclip as taxons' image adapter in the next major version.
Please, use the provided generator to incorporate the current Paperclip adapter in your application with:

bin/rails g solidus:paperclip_adapter:install
MSG
end

preferences[:taxon_attachment_module] = value
end


# Configures the absolute path that contains the Solidus engine
# migrations. This will be checked at app boot to confirm that all Solidus
Expand Down
13 changes: 11 additions & 2 deletions core/lib/spree/testing_support/dummy_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'active_storage/engine'
require 'generators/solidus/paperclip_adapter/install/install_generator'

Rails.env = 'test'

Expand Down Expand Up @@ -41,6 +42,14 @@ def self.setup(gem_root:, lib_name:, auto_migrate: true)
if auto_migrate
DummyApp::Migrations.auto_migrate
end

if ENV['DISABLE_ACTIVE_STORAGE'] == 'true'
Rails::Generators.invoke('solidus:paperclip_adapter:install', [
"--set_preferences=false",
"--app_directory=#{DummyApp::Application.config.root}",
"--app_name=DummyApp",
])
end
end

class Application < ::Rails::Application
Expand Down Expand Up @@ -135,8 +144,8 @@ class Application < ::Rails::Application
Spree.load_defaults(Spree.solidus_version)
Spree.config do |config|
if (ENV['DISABLE_ACTIVE_STORAGE'] == 'true')
config.image_attachment_module = 'Spree::Image::PaperclipAttachment'
config.taxon_attachment_module = 'Spree::Taxon::PaperclipAttachment'
config.image_attachment_module = 'DummyApp::Image::PaperclipAttachment'
config.taxon_attachment_module = 'DummyApp::Taxon::PaperclipAttachment'
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

require 'rails_helper'
require 'generators/solidus/paperclip_adapter/install/install_generator'

RSpec.describe Solidus::PaperclipAdapter::InstallGenerator do
let(:initializer_directory) { Rails.root.join('tmp') }
let(:initializer_basename) { 'spree' }
let(:initializer) { File.join(initializer_directory, "#{initializer_basename}.rb") }
let(:image_adapter_path) { Rails.root.join('app', 'models', 'my_store', 'image', 'paperclip_attachment.rb') }
let(:taxon_adapter_path) { Rails.root.join('app', 'models', 'my_store', 'taxon', 'paperclip_attachment.rb') }
let(:cleanup) {
proc {
File.delete(initializer) if File.exist?(initializer)
File.delete(image_adapter_path) if File.exist?(image_adapter_path)
File.delete(taxon_adapter_path) if File.exist?(taxon_adapter_path)
}
}
let(:create_initializer) {
proc {
File.write(initializer,
<<~RUBY
Spree.config do |config|
# ...
#
# Configure adapter for attachments on products and taxons (use ActiveStorageAttachment or PaperclipAttachment)
config.image_attachment_module = 'Spree::Image::PaperclipAttachment'
config.taxon_attachment_module = 'Spree::Taxon::PaperclipAttachment'
end
RUBY
)
}
}
let(:invoke) do
lambda do
Rails::Generators.invoke('solidus:paperclip_adapter:install', [
"--initializer_directory=tmp",
"--initializer_basename=spree",
"--app_directory=#{Rails.root}",
"--app_name=MyStore",
"--quiet"
])
end
end

before { create_initializer.call }
after { cleanup.call }

it 'changes attachment adapter configuration' do
invoke.call

expect(File.read(initializer)).to include(
<<~RUBY
Spree.config do |config|
# ...
#
# Configure adapter for attachments on products and taxons (use ActiveStorageAttachment or PaperclipAttachment)
config.image_attachment_module = 'MyStore::Image::PaperclipAttachment'
config.taxon_attachment_module = 'MyStore::Taxon::PaperclipAttachment'
end
RUBY
)
end

it 'copies adapter files at the right location' do
invoke.call

image_adapter_path = Rails.root.join('app', 'models', 'my_store', 'image', 'paperclip_attachment.rb')
expect(File.read(image_adapter_path)).to include(
<<~RUBY
module MyStore
module Image
module PaperclipAttachment
RUBY
)

expect(File.read(taxon_adapter_path)).to include(
<<~RUBY
module MyStore
module Taxon
module PaperclipAttachment
RUBY
)
end
end