Restrict variants to variable image blobs

This commit is contained in:
George Claghorn 2017-12-15 10:45:00 -05:00
parent 3ddb811acc
commit 311af752cf
4 changed files with 27 additions and 4 deletions

View File

@ -16,6 +16,7 @@ require "active_storage/analyzer/null_analyzer"
# update a blob's metadata on a subsequent pass, but you should not update the key or change the uploaded file.
# If you need to create a derivative or otherwise change the blob, simply create a new blob and purge the old one.
class ActiveStorage::Blob < ActiveRecord::Base
class InvariableError < StandardError; end
class UnpreviewableError < StandardError; end
class UnrepresentableError < StandardError; end
@ -110,6 +111,7 @@ class ActiveStorage::Blob < ActiveRecord::Base
content_type.start_with?("text")
end
# Returns an ActiveStorage::Variant instance with the set of +transformations+ provided. This is only relevant for image
# files, and it allows any image to be transformed for size, colors, and the like. Example:
#
@ -125,8 +127,20 @@ class ActiveStorage::Blob < ActiveRecord::Base
#
# This will create a URL for that specific blob with that specific variant, which the ActiveStorage::VariantsController
# can then produce on-demand.
#
# Raises ActiveStorage::Blob::InvariableError if ImageMagick cannot transform the blob. To determine whether a blob is
# variable, call ActiveStorage::Blob#previewable?.
def variant(transformations)
ActiveStorage::Variant.new(self, ActiveStorage::Variation.wrap(transformations))
if variable?
ActiveStorage::Variant.new(self, ActiveStorage::Variation.wrap(transformations))
else
raise InvariableError
end
end
# Returns true if ImageMagick can transform the blob (its content type is in +ActiveStorage.variable_content_types+).
def variable?
ActiveStorage.variable_content_types.include?(content_type)
end
@ -170,16 +184,16 @@ class ActiveStorage::Blob < ActiveRecord::Base
case
when previewable?
preview transformations
when image?
when variable?
variant transformations
else
raise UnrepresentableError
end
end
# Returns true if the blob is an image or is previewable.
# Returns true if the blob is variable or is previewable.
def representable?
image? || previewable?
variable? || previewable?
end

View File

@ -41,4 +41,5 @@ module ActiveStorage
mattr_accessor :queue
mattr_accessor :previewers, default: []
mattr_accessor :analyzers, default: []
mattr_accessor :variable_content_types, default: []
end

View File

@ -16,6 +16,7 @@ module ActiveStorage
config.active_storage = ActiveSupport::OrderedOptions.new
config.active_storage.previewers = [ ActiveStorage::Previewer::PDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
config.active_storage.analyzers = [ ActiveStorage::Analyzer::ImageAnalyzer, ActiveStorage::Analyzer::VideoAnalyzer ]
config.active_storage.variable_content_types = [ "image/png", "image/gif", "image/jpg", "image/jpeg", "image/vnd.adobe.photoshop" ]
config.active_storage.paths = ActiveSupport::OrderedOptions.new
config.eager_load_namespaces << ActiveStorage
@ -26,6 +27,7 @@ module ActiveStorage
ActiveStorage.queue = app.config.active_storage.queue
ActiveStorage.previewers = app.config.active_storage.previewers || []
ActiveStorage.analyzers = app.config.active_storage.analyzers || []
ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
end
end

View File

@ -27,6 +27,12 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
assert_match(/Gray/, image.colorspace)
end
test "variation of invariable blob" do
assert_raises ActiveStorage::Blob::InvariableError do
create_file_blob(filename: "report.pdf", content_type: "application/pdf").variant(resize: "100x100")
end
end
test "service_url doesn't grow in length despite long variant options" do
variant = @blob.variant(font: "a" * 10_000).processed
assert_operator variant.service_url.length, :<, 500