-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3501 from filippoliverani/add-active-storage-adapter
Add ActiveStorage adapter
- Loading branch information
Showing
22 changed files
with
448 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
core/app/models/concerns/spree/active_storage_adapter.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree | ||
# Adapts ActiveStorage interface to make it compliant with Solidus' | ||
# Paperclip-oriented attachment support. | ||
module ActiveStorageAdapter | ||
extend ActiveSupport::Concern | ||
include Spree::ActiveStorageAdapter::Normalization | ||
|
||
included do | ||
next if Rails.gem_version >= Gem::Version.new('6.1.0.alpha') | ||
|
||
abort <<~MESSAGE | ||
Configuration Error: Solidus ActiveStorage attachment adpater requires Rails >= 6.1.0. | ||
Spree::Config.image_attachment_module preference is set to #{Spree::Config.image_attachment_module} | ||
Spree::Config.taxon_attachment_module preference is set to #{Spree::Config.taxon_attachment_module} | ||
Rails version is #{Rails.gem_version} | ||
To solve the problem you can upgrade to a Rails version greater than or equal to 6.1.0 | ||
or use legacy Paperclip attachment adapter by editing `config/initialiers/spree/rb`: | ||
config.image_attachment_module = 'Spree::Image::PaperclipAttachment' | ||
config.taxon_attachment_module = 'Spree::Taxon::PaperclipAttachment' | ||
MESSAGE | ||
end | ||
|
||
class_methods do | ||
attr_reader :attachment_name | ||
attr_reader :attachment_definition | ||
|
||
# Specifies the relation between a single attachment and the model | ||
def has_attachment(name, definition) | ||
@attachment_name = name.to_sym | ||
@attachment_definition = definition | ||
|
||
has_one_attached attachment_name | ||
|
||
override_reader | ||
override_writer | ||
define_image_validation | ||
define_presence_reader | ||
end | ||
|
||
def attachment_definitions | ||
{ attachment_name => attachment_definition } | ||
end | ||
|
||
private | ||
|
||
def override_reader | ||
method_name = attachment_name | ||
override = Module.new do | ||
define_method method_name do |*args| | ||
attachment = Attachment.new(super(), styles: styles) | ||
if args.empty? | ||
attachment | ||
else | ||
style = args.first || default_style | ||
attachment.url(style) | ||
end | ||
end | ||
end | ||
prepend override | ||
|
||
alias_method :attachment, method_name if method_name != :attachment | ||
end | ||
|
||
def override_writer | ||
method_name = :"#{attachment_name}=" | ||
override = Module.new do | ||
define_method method_name do |attachable| | ||
no_other_changes = persisted? && !changed? | ||
super(normalize_attachable(attachable)) | ||
save if no_other_changes | ||
end | ||
end | ||
prepend override | ||
end | ||
|
||
def define_image_validation | ||
define_method :"#{attachment_name}_is_an_image" do | ||
return unless attachment.attached? | ||
return if attachment.image? | ||
|
||
errors.add(self.class.attachment_name, 'is not an image') | ||
end | ||
end | ||
|
||
def define_presence_reader | ||
define_method :"#{attachment_name}_present?" do | ||
attachment.attached? | ||
end | ||
end | ||
end | ||
|
||
def styles | ||
self.class.attachment_definition[:styles] | ||
end | ||
|
||
def default_style | ||
self.class.attachment_definition[:default_style] | ||
end | ||
|
||
def filename | ||
attachment.filename | ||
end | ||
|
||
def url(style = default_style) | ||
attachment.url(style) | ||
end | ||
|
||
def destroy_attachment(_name) | ||
attachment.destroy | ||
end | ||
end | ||
end |
69 changes: 69 additions & 0 deletions
69
core/app/models/concerns/spree/active_storage_adapter/attachment.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'mini_magick' | ||
|
||
module Spree | ||
module ActiveStorageAdapter | ||
# Decorares AtiveStorage attachment to add methods exptected by Solidus' | ||
# Paperclip-oriented attachment support. | ||
class Attachment | ||
delegate_missing_to :@attachment | ||
|
||
DEFAULT_SIZE = '100%' | ||
|
||
def initialize(attachment, styles: {}) | ||
@attachment = attachment | ||
@styles = styles | ||
end | ||
|
||
def exists? | ||
attached? | ||
end | ||
|
||
def filename | ||
blob.filename.to_s | ||
end | ||
|
||
def url(style = nil) | ||
variant(style).url | ||
end | ||
|
||
def variant(style = nil) | ||
size = style_to_size(style&.to_sym) | ||
@attachment.variant( | ||
resize: size, | ||
strip: true, | ||
'auto-orient': true, | ||
colorspace: 'sRGB', | ||
).processed | ||
end | ||
|
||
def height | ||
metadata[:height] | ||
end | ||
|
||
def width | ||
metadata[:width] | ||
end | ||
|
||
def destroy | ||
return false unless attached? | ||
|
||
purge | ||
true | ||
end | ||
|
||
private | ||
|
||
def metadata | ||
analyze unless analyzed? | ||
|
||
@attachment.metadata | ||
end | ||
|
||
def style_to_size(style) | ||
@styles.fetch(style) { DEFAULT_SIZE } | ||
end | ||
end | ||
end | ||
end |
39 changes: 39 additions & 0 deletions
39
core/app/models/concerns/spree/active_storage_adapter/normalization.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree | ||
module ActiveStorageAdapter | ||
# Contains normalization methods to make objects compliant with | ||
# ActiveStorage API. | ||
module Normalization | ||
# Normalizes an attachable | ||
def normalize_attachable(attachable) | ||
case attachable | ||
when ActiveStorage::Blob, ActionDispatch::Http::UploadedFile, | ||
Rack::Test::UploadedFile, Hash, String | ||
attachable | ||
when Attachment, ActiveStorage::Attached | ||
attachable_blob(attachable) | ||
else # assume it's an IO | ||
attachable_io(attachable) | ||
end | ||
end | ||
|
||
private | ||
|
||
def attachable_blob(attachable) | ||
attachable.blob | ||
end | ||
|
||
def attachable_io(attachable) | ||
filename = if attachable.respond_to?(:to_path) | ||
attachable.to_path | ||
else | ||
SecureRandom.uuid | ||
end | ||
attachable.rewind | ||
|
||
{ io: attachable, filename: filename } | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree::Image::ActiveStorageAttachment | ||
extend ActiveSupport::Concern | ||
include Spree::ActiveStorageAdapter | ||
|
||
delegate :width, :height, to: :attachment, prefix: true | ||
|
||
included do | ||
has_attachment :attachment, | ||
styles: { | ||
mini: '48x48>', | ||
small: '400x400>', | ||
product: '680x680>', | ||
large: '1200x1200>' | ||
}, | ||
default_style: :product | ||
validates :attachment, presence: true | ||
validate :attachment_is_an_image | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree::Taxon::ActiveStorageAttachment | ||
extend ActiveSupport::Concern | ||
include Spree::ActiveStorageAdapter | ||
|
||
included do | ||
has_attachment :icon, | ||
styles: { mini: '32x32>', normal: '128x128>' }, | ||
default_style: :mini | ||
validate :icon_is_an_image | ||
|
||
|
||
end | ||
|
||
def attachment_partial_name | ||
'paperclip' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,44 @@ | ||
# frozen_string_literal: true | ||
|
||
module AwesomeNestedSetOvveride | ||
# Add :polimorphic key option only when used to make it work with Rails 6.1+ | ||
# https://github.com/osmaelo/rails/commit/2c008d9f6311d92b3660193285230505e74a114f | ||
# Add :polimorphic key option only when used to make it work with Rails 6.1+, | ||
# required since rails/rails@2c008d9 | ||
# This can be removed when upgrading to an awesome_nested_set version | ||
# compliant with Rails 6.1+. | ||
def acts_as_nested_set_relate_parent! | ||
# Disable Rubocop to keep original code for diffs | ||
# rubocop:disable | ||
options = { | ||
:class_name => self.base_class.to_s, | ||
:foreign_key => parent_column_name, | ||
:primary_key => primary_column_name, | ||
:counter_cache => acts_as_nested_set_options[:counter_cache], | ||
:inverse_of => (:children unless acts_as_nested_set_options[:polymorphic]), | ||
:touch => acts_as_nested_set_options[:touch] | ||
} | ||
options[:polymorphic] = true if acts_as_nested_set_options[:polymorphic] | ||
options[:optional] = true if ActiveRecord::VERSION::MAJOR >= 5 | ||
belongs_to :parent, options | ||
# rubocop:disable | ||
# compliant with Rails 6.1+, already addressed in | ||
# collectiveidea/awesome_nested_set#421 | ||
module RelateParent | ||
def acts_as_nested_set_relate_parent! | ||
# Disable Rubocop to keep original code for diffs | ||
# rubocop:disable | ||
options = { | ||
:class_name => self.base_class.to_s, | ||
:foreign_key => parent_column_name, | ||
:primary_key => primary_column_name, | ||
:counter_cache => acts_as_nested_set_options[:counter_cache], | ||
:inverse_of => (:children unless acts_as_nested_set_options[:polymorphic]), | ||
:touch => acts_as_nested_set_options[:touch] | ||
} | ||
options[:polymorphic] = true if acts_as_nested_set_options[:polymorphic] | ||
options[:optional] = true if ActiveRecord::VERSION::MAJOR >= 5 | ||
belongs_to :parent, options | ||
# rubocop:enable | ||
end | ||
|
||
CollectiveIdea::Acts::NestedSet.prepend self | ||
end | ||
|
||
CollectiveIdea::Acts::NestedSet.prepend self | ||
# Skip breaking model reload before update depth. Already addressed in | ||
# collectiveidea/awesome_nested_set#413 | ||
# This can be removed when a new version of awesome_nested_set is released. | ||
module Model | ||
def set_depth! | ||
return unless has_depth_column? | ||
|
||
in_tenacious_transaction do | ||
update_depth(level) | ||
end | ||
end | ||
|
||
CollectiveIdea::Acts::NestedSet::Model.prepend self | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.