Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
d4cdd4a0
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d4cdd4a0
编写于
1月 10, 2018
作者:
G
George Claghorn
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Extract Analyzable and Representable concerns
上级
5a593486
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
158 addition
and
150 deletion
+158
-150
activestorage/app/models/active_storage/blob.rb
activestorage/app/models/active_storage/blob.rb
+2
-147
activestorage/app/models/active_storage/blob/analyzable.rb
activestorage/app/models/active_storage/blob/analyzable.rb
+55
-0
activestorage/app/models/active_storage/blob/representable.rb
...vestorage/app/models/active_storage/blob/representable.rb
+91
-0
activestorage/lib/active_storage.rb
activestorage/lib/active_storage.rb
+2
-0
activestorage/lib/active_storage/errors.rb
activestorage/lib/active_storage/errors.rb
+5
-0
activestorage/test/models/preview_test.rb
activestorage/test/models/preview_test.rb
+1
-1
activestorage/test/models/representation_test.rb
activestorage/test/models/representation_test.rb
+1
-1
activestorage/test/models/variant_test.rb
activestorage/test/models/variant_test.rb
+1
-1
未找到文件。
activestorage/app/models/active_storage/blob.rb
浏览文件 @
d4cdd4a0
# frozen_string_literal: true
require
"active_storage/analyzer/null_analyzer"
# A blob is a record that contains the metadata about a file and a key for where that file resides on the service.
# Blobs can be created in two ways:
#
...
...
@@ -16,9 +14,7 @@
# 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
include
Analyzable
,
Representable
self
.
table_name
=
"active_storage_blobs"
...
...
@@ -29,8 +25,6 @@ class UnrepresentableError < StandardError; end
has_many
:attachments
has_one_attached
:preview_image
class
<<
self
# You can used the signed ID of a blob to refer to it on the client side without fear of tampering.
# This is particularly helpful for direct uploads where the client-side needs to refer to the blob
...
...
@@ -69,7 +63,6 @@ def create_before_direct_upload!(filename:, byte_size:, checksum:, content_type:
end
end
# Returns a signed ID for this blob that's suitable for reference on the client-side without fear of tampering.
# It uses the framework-wide verifier on <tt>ActiveStorage.verifier</tt>, but with a dedicated purpose.
def
signed_id
...
...
@@ -112,91 +105,6 @@ def 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:
#
# avatar.variant(resize: "100x100").processed.service_url
#
# This will create and process a variant of the avatar blob that's constrained to a height and width of 100px.
# Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
#
# Frequently, though, you don't actually want to transform the variant right away. But rather simply refer to a
# specific variant that can be created by a controller on-demand. Like so:
#
# <%= image_tag Current.user.avatar.variant(resize: "100x100") %>
#
# 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
)
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
# Returns an ActiveStorage::Preview instance with the set of +transformations+ provided. A preview is an image generated
# from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer
# extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.
#
# blob.preview(resize: "100x100").processed.service_url
#
# Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand.
# Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s
# how to use the built-in version:
#
# <%= image_tag video.preview(resize: "100x100") %>
#
# This method raises ActiveStorage::Blob::UnpreviewableError if no previewer accepts the receiving blob. To determine
# whether a blob is accepted by any previewer, call ActiveStorage::Blob#previewable?.
def
preview
(
transformations
)
if
previewable?
ActiveStorage
::
Preview
.
new
(
self
,
ActiveStorage
::
Variation
.
wrap
(
transformations
))
else
raise
UnpreviewableError
end
end
# Returns true if any registered previewer accepts the blob. By default, this will return true for videos and PDF documents.
def
previewable?
ActiveStorage
.
previewers
.
any?
{
|
klass
|
klass
.
accept?
(
self
)
}
end
# Returns an ActiveStorage::Preview for a previewable blob or an ActiveStorage::Variant for a variable image blob.
#
# blob.representation(resize: "100x100").processed.service_url
#
# Raises ActiveStorage::Blob::UnrepresentableError if the receiving blob is neither variable 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
variable?
variant
transformations
else
raise
UnrepresentableError
end
end
# Returns true if the blob is variable or previewable.
def
representable?
variable?
||
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
...
...
@@ -216,6 +124,7 @@ def service_headers_for_direct_upload
service
.
headers_for_direct_upload
key
,
filename:
filename
,
content_type:
content_type
,
content_length:
byte_size
,
checksum:
checksum
end
# Uploads the +io+ to the service on the +key+ for this blob. Blobs are intended to be immutable, so you shouldn't be
# using this method after a file has already been uploaded to fit with a blob. If you want to create a derivative blob,
# you should instead simply create a new blob based on the old one.
...
...
@@ -240,46 +149,6 @@ def download(&block)
end
# Extracts and stores metadata from the file associated with this blob using a relevant analyzer. Active Storage comes
# with built-in analyzers for images and videos. See ActiveStorage::Analyzer::ImageAnalyzer and
# ActiveStorage::Analyzer::VideoAnalyzer for information about the specific attributes they extract and the third-party
# libraries they require.
#
# To choose the analyzer for a blob, Active Storage calls +accept?+ on each registered analyzer in order. It uses the
# first analyzer for which +accept?+ returns true when given the blob. If no registered analyzer accepts the blob, no
# metadata is extracted from it.
#
# In a Rails application, add or remove analyzers by manipulating +Rails.application.config.active_storage.analyzers+
# in an initializer:
#
# # Add a custom analyzer for Microsoft Office documents:
# Rails.application.config.active_storage.analyzers.append DOCXAnalyzer
#
# # Remove the built-in video analyzer:
# Rails.application.config.active_storage.analyzers.delete ActiveStorage::Analyzer::VideoAnalyzer
#
# Outside of a Rails application, manipulate +ActiveStorage.analyzers+ instead.
#
# You won't ordinarily need to call this method from a Rails application. New blobs are automatically and asynchronously
# analyzed via #analyze_later when they're attached for the first time.
def
analyze
update!
metadata:
metadata
.
merge
(
extract_metadata_via_analyzer
)
end
# Enqueues an ActiveStorage::AnalyzeJob which calls #analyze.
#
# This method is automatically called for a blob when it's attached for the first time. You can call it to analyze a blob
# again (e.g. if you add a new analyzer or modify an existing one).
def
analyze_later
ActiveStorage
::
AnalyzeJob
.
perform_later
(
self
)
end
# Returns true if the blob has been analyzed.
def
analyzed?
analyzed
end
# Deletes the file on the service that's associated with this blob. This should only be done if the blob is going to be
# deleted as well or you will essentially have a dead reference. It's recommended to use the +#purge+ and +#purge_later+
# methods in most circumstances.
...
...
@@ -313,20 +182,6 @@ def compute_checksum_in_chunks(io)
end
.
base64digest
end
def
extract_metadata_via_analyzer
analyzer
.
metadata
.
merge
(
analyzed:
true
)
end
def
analyzer
analyzer_class
.
new
(
self
)
end
def
analyzer_class
ActiveStorage
.
analyzers
.
detect
{
|
klass
|
klass
.
accept?
(
self
)
}
||
ActiveStorage
::
Analyzer
::
NullAnalyzer
end
def
forcibly_serve_as_binary?
ActiveStorage
.
content_types_to_serve_as_binary
.
include?
(
content_type
)
end
...
...
activestorage/app/models/active_storage/blob/analyzable.rb
0 → 100644
浏览文件 @
d4cdd4a0
require
"active_storage/analyzer/null_analyzer"
module
ActiveStorage::Blob::Analyzable
# Extracts and stores metadata from the file associated with this blob using a relevant analyzer. Active Storage comes
# with built-in analyzers for images and videos. See ActiveStorage::Analyzer::ImageAnalyzer and
# ActiveStorage::Analyzer::VideoAnalyzer for information about the specific attributes they extract and the third-party
# libraries they require.
#
# To choose the analyzer for a blob, Active Storage calls +accept?+ on each registered analyzer in order. It uses the
# first analyzer for which +accept?+ returns true when given the blob. If no registered analyzer accepts the blob, no
# metadata is extracted from it.
#
# In a Rails application, add or remove analyzers by manipulating +Rails.application.config.active_storage.analyzers+
# in an initializer:
#
# # Add a custom analyzer for Microsoft Office documents:
# Rails.application.config.active_storage.analyzers.append DOCXAnalyzer
#
# # Remove the built-in video analyzer:
# Rails.application.config.active_storage.analyzers.delete ActiveStorage::Analyzer::VideoAnalyzer
#
# Outside of a Rails application, manipulate +ActiveStorage.analyzers+ instead.
#
# You won't ordinarily need to call this method from a Rails application. New blobs are automatically and asynchronously
# analyzed via #analyze_later when they're attached for the first time.
def
analyze
update!
metadata:
metadata
.
merge
(
extract_metadata_via_analyzer
)
end
# Enqueues an ActiveStorage::AnalyzeJob which calls #analyze.
#
# This method is automatically called for a blob when it's attached for the first time. You can call it to analyze a blob
# again (e.g. if you add a new analyzer or modify an existing one).
def
analyze_later
ActiveStorage
::
AnalyzeJob
.
perform_later
(
self
)
end
# Returns true if the blob has been analyzed.
def
analyzed?
analyzed
end
private
def
extract_metadata_via_analyzer
analyzer
.
metadata
.
merge
(
analyzed:
true
)
end
def
analyzer
analyzer_class
.
new
(
self
)
end
def
analyzer_class
ActiveStorage
.
analyzers
.
detect
{
|
klass
|
klass
.
accept?
(
self
)
}
||
ActiveStorage
::
Analyzer
::
NullAnalyzer
end
end
activestorage/app/models/active_storage/blob/representable.rb
0 → 100644
浏览文件 @
d4cdd4a0
module
ActiveStorage::Blob::Representable
extend
ActiveSupport
::
Concern
included
do
has_one_attached
:preview_image
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:
#
# avatar.variant(resize: "100x100").processed.service_url
#
# This will create and process a variant of the avatar blob that's constrained to a height and width of 100px.
# Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
#
# Frequently, though, you don't actually want to transform the variant right away. But rather simply refer to a
# specific variant that can be created by a controller on-demand. Like so:
#
# <%= image_tag Current.user.avatar.variant(resize: "100x100") %>
#
# 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
)
if
variable?
ActiveStorage
::
Variant
.
new
(
self
,
ActiveStorage
::
Variation
.
wrap
(
transformations
))
else
raise
ActiveStorage
::
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
# Returns an ActiveStorage::Preview instance with the set of +transformations+ provided. A preview is an image generated
# from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer
# extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.
#
# blob.preview(resize: "100x100").processed.service_url
#
# Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand.
# Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s
# how to use the built-in version:
#
# <%= image_tag video.preview(resize: "100x100") %>
#
# This method raises ActiveStorage::Blob::UnpreviewableError if no previewer accepts the receiving blob. To determine
# whether a blob is accepted by any previewer, call ActiveStorage::Blob#previewable?.
def
preview
(
transformations
)
if
previewable?
ActiveStorage
::
Preview
.
new
(
self
,
ActiveStorage
::
Variation
.
wrap
(
transformations
))
else
raise
ActiveStorage
::
UnpreviewableError
end
end
# Returns true if any registered previewer accepts the blob. By default, this will return true for videos and PDF documents.
def
previewable?
ActiveStorage
.
previewers
.
any?
{
|
klass
|
klass
.
accept?
(
self
)
}
end
# Returns an ActiveStorage::Preview for a previewable blob or an ActiveStorage::Variant for a variable image blob.
#
# blob.representation(resize: "100x100").processed.service_url
#
# Raises ActiveStorage::Blob::UnrepresentableError if the receiving blob is neither variable 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
variable?
variant
transformations
else
raise
ActiveStorage
::
UnrepresentableError
end
end
# Returns true if the blob is variable or previewable.
def
representable?
variable?
||
previewable?
end
end
activestorage/lib/active_storage.rb
浏览文件 @
d4cdd4a0
...
...
@@ -26,7 +26,9 @@
require
"active_record"
require
"active_support"
require
"active_support/rails"
require
"active_storage/version"
require
"active_storage/errors"
module
ActiveStorage
extend
ActiveSupport
::
Autoload
...
...
activestorage/lib/active_storage/errors.rb
0 → 100644
浏览文件 @
d4cdd4a0
module
ActiveStorage
class
InvariableError
<
StandardError
;
end
class
UnpreviewableError
<
StandardError
;
end
class
UnrepresentableError
<
StandardError
;
end
end
activestorage/test/models/preview_test.rb
浏览文件 @
d4cdd4a0
...
...
@@ -33,7 +33,7 @@ class ActiveStorage::PreviewTest < ActiveSupport::TestCase
test
"previewing an unpreviewable blob"
do
blob
=
create_file_blob
assert_raises
ActiveStorage
::
Blob
::
UnpreviewableError
do
assert_raises
ActiveStorage
::
UnpreviewableError
do
blob
.
preview
resize:
"640x280"
end
end
...
...
activestorage/test/models/representation_test.rb
浏览文件 @
d4cdd4a0
...
...
@@ -34,7 +34,7 @@ class ActiveStorage::RepresentationTest < ActiveSupport::TestCase
test
"representing an unrepresentable blob"
do
blob
=
create_blob
assert_raises
ActiveStorage
::
Blob
::
UnrepresentableError
do
assert_raises
ActiveStorage
::
UnrepresentableError
do
blob
.
representation
resize:
"100x100"
end
end
...
...
activestorage/test/models/variant_test.rb
浏览文件 @
d4cdd4a0
...
...
@@ -59,7 +59,7 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
end
test
"variation of invariable blob"
do
assert_raises
ActiveStorage
::
Blob
::
InvariableError
do
assert_raises
ActiveStorage
::
InvariableError
do
create_file_blob
(
filename:
"report.pdf"
,
content_type:
"application/pdf"
).
variant
(
resize:
"100x100"
)
end
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录