aboutsummaryrefslogtreecommitdiffstats
path: root/activestorage/app
diff options
context:
space:
mode:
Diffstat (limited to 'activestorage/app')
-rw-r--r--activestorage/app/models/active_storage/blob.rb30
-rw-r--r--activestorage/app/models/active_storage/variant.rb6
-rw-r--r--activestorage/app/models/active_storage/variation.rb15
3 files changed, 43 insertions, 8 deletions
diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb
index ff785d4f61..84b8f3827b 100644
--- a/activestorage/app/models/active_storage/blob.rb
+++ b/activestorage/app/models/active_storage/blob.rb
@@ -15,6 +15,7 @@
# 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 UnpreviewableError < StandardError; end
+ class UnrepresentableError < StandardError; end
self.table_name = "active_storage_blobs"
@@ -123,7 +124,7 @@ 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.
def variant(transformations)
- ActiveStorage::Variant.new(self, ActiveStorage::Variation.new(transformations))
+ ActiveStorage::Variant.new(self, ActiveStorage::Variation.wrap(transformations))
end
@@ -143,7 +144,7 @@ class ActiveStorage::Blob < ActiveRecord::Base
# whether a blob is accepted by any previewer, call ActiveStorage::Blob#previewable?.
def preview(transformations)
if previewable?
- ActiveStorage::Preview.new(self, ActiveStorage::Variation.new(transformations))
+ ActiveStorage::Preview.new(self, ActiveStorage::Variation.wrap(transformations))
else
raise UnpreviewableError
end
@@ -155,6 +156,31 @@ class ActiveStorage::Blob < ActiveRecord::Base
end
+ # Returns an ActiveStorage::Preview instance for a previewable blob or an ActiveStorage::Variant instance for an image blob.
+ #
+ # blob.representation(resize: "100x100").processed.service_url
+ #
+ # Raises ActiveStorage::Blob::UnrepresentableError if the receiving blob is neither an image nor previewable. Call
+ # ActiveStorage::Blob#representable? to determine whether a blob is representable.
+ #
+ # See ActiveStorage::Blob#preview and ActiveStorage::Blob#variant for more information.
+ def representation(transformations)
+ case
+ when previewable?
+ preview transformations
+ when image?
+ variant transformations
+ else
+ raise UnrepresentableError
+ end
+ end
+
+ # Returns true if the blob is an image or is previewable.
+ def representable?
+ image? || previewable?
+ end
+
+
# Returns the URL of the blob on the service. This URL is intended to be short-lived for security and not used directly
# with users. Instead, the +service_url+ should only be exposed as a redirect from a stable, possibly authenticated URL.
# Hiding the +service_url+ behind a redirect also gives you the power to change services without updating all URLs. And
diff --git a/activestorage/app/models/active_storage/variant.rb b/activestorage/app/models/active_storage/variant.rb
index 54685b4c0e..fa5aa69bd3 100644
--- a/activestorage/app/models/active_storage/variant.rb
+++ b/activestorage/app/models/active_storage/variant.rb
@@ -50,7 +50,7 @@ class ActiveStorage::Variant
# Returns a combination key of the blob and the variation that together identifies a specific variant.
def key
- "variants/#{blob.key}/#{variation.key}"
+ "variants/#{blob.key}/#{Digest::SHA256.hexdigest(variation.key)}"
end
# Returns the URL of the variant on the service. This URL is intended to be short-lived for security and not used directly
@@ -65,6 +65,10 @@ class ActiveStorage::Variant
service.url key, expires_in: expires_in, disposition: disposition, filename: blob.filename, content_type: blob.content_type
end
+ # Returns the receiving variant. Allows ActiveStorage::Variant and ActiveStorage::Preview instances to be used interchangeably.
+ def image
+ self
+ end
private
def processed?
diff --git a/activestorage/app/models/active_storage/variation.rb b/activestorage/app/models/active_storage/variation.rb
index df2643442a..13bad87cac 100644
--- a/activestorage/app/models/active_storage/variation.rb
+++ b/activestorage/app/models/active_storage/variation.rb
@@ -13,16 +13,21 @@ class ActiveStorage::Variation
attr_reader :transformations
class << self
- def wrap(variation_or_key)
- case variation_or_key
+ # Returns a Variation instance based on the given variator. If the variator is a Variation, it is
+ # returned unmodified. If it is a String, it is passed to ActiveStorage::Variation.decode. Otherwise,
+ # it is assumed to be a transformations Hash and is passed directly to the constructor.
+ def wrap(variator)
+ case variator
when self
- variation_or_key
+ variator
+ when String
+ decode variator
else
- decode variation_or_key
+ new variator
end
end
- # Returns a variation instance with the transformations that were encoded by +encode+.
+ # Returns a Variation instance with the transformations that were encoded by +encode+.
def decode(key)
new ActiveStorage.verifier.verify(key, purpose: :variation)
end