activestorage 5.2.7.1 → 6.1.4.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activestorage might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +225 -93
- data/MIT-LICENSE +1 -1
- data/README.md +43 -8
- data/app/assets/javascripts/activestorage.js +5 -2
- data/app/controllers/active_storage/base_controller.rb +13 -4
- data/app/controllers/active_storage/blobs/proxy_controller.rb +14 -0
- data/app/controllers/active_storage/{blobs_controller.rb → blobs/redirect_controller.rb} +3 -3
- data/app/controllers/active_storage/direct_uploads_controller.rb +2 -2
- data/app/controllers/active_storage/disk_controller.rb +13 -22
- data/app/controllers/active_storage/representations/base_controller.rb +14 -0
- data/app/controllers/active_storage/representations/proxy_controller.rb +13 -0
- data/app/controllers/active_storage/{representations_controller.rb → representations/redirect_controller.rb} +3 -5
- data/app/controllers/concerns/active_storage/file_server.rb +18 -0
- data/app/controllers/concerns/active_storage/set_blob.rb +1 -1
- data/app/controllers/concerns/active_storage/set_current.rb +15 -0
- data/app/controllers/concerns/active_storage/set_headers.rb +12 -0
- data/app/javascript/activestorage/blob_record.js +7 -2
- data/app/jobs/active_storage/analyze_job.rb +5 -0
- data/app/jobs/active_storage/base_job.rb +0 -1
- data/app/jobs/active_storage/mirror_job.rb +15 -0
- data/app/jobs/active_storage/purge_job.rb +3 -0
- data/app/models/active_storage/attachment.rb +35 -16
- data/app/models/active_storage/blob/analyzable.rb +6 -2
- data/app/models/active_storage/blob/identifiable.rb +7 -6
- data/app/models/active_storage/blob/representable.rb +36 -6
- data/app/models/active_storage/blob.rb +186 -68
- data/app/models/active_storage/filename.rb +0 -6
- data/app/models/active_storage/preview.rb +37 -12
- data/app/models/active_storage/record.rb +7 -0
- data/app/models/active_storage/variant.rb +53 -67
- data/app/models/active_storage/variant_record.rb +8 -0
- data/app/models/active_storage/variant_with_record.rb +54 -0
- data/app/models/active_storage/variation.rb +30 -94
- data/config/routes.rb +66 -15
- data/db/migrate/20170806125915_create_active_storage_tables.rb +14 -5
- data/db/update_migrate/20190112182829_add_service_name_to_active_storage_blobs.rb +17 -0
- data/db/update_migrate/20191206030411_create_active_storage_variant_records.rb +11 -0
- data/lib/active_storage/analyzer/image_analyzer.rb +14 -4
- data/lib/active_storage/analyzer/null_analyzer.rb +4 -0
- data/lib/active_storage/analyzer/video_analyzer.rb +17 -8
- data/lib/active_storage/analyzer.rb +15 -4
- data/lib/active_storage/attached/changes/create_many.rb +47 -0
- data/lib/active_storage/attached/changes/create_one.rb +82 -0
- data/lib/active_storage/attached/changes/create_one_of_many.rb +10 -0
- data/lib/active_storage/attached/changes/delete_many.rb +27 -0
- data/lib/active_storage/attached/changes/delete_one.rb +19 -0
- data/lib/active_storage/attached/changes.rb +16 -0
- data/lib/active_storage/attached/many.rb +19 -12
- data/lib/active_storage/attached/model.rb +212 -0
- data/lib/active_storage/attached/one.rb +19 -21
- data/lib/active_storage/attached.rb +7 -22
- data/lib/active_storage/downloader.rb +43 -0
- data/lib/active_storage/engine.rb +60 -38
- data/lib/active_storage/errors.rb +25 -3
- data/lib/active_storage/gem_version.rb +4 -4
- data/lib/active_storage/log_subscriber.rb +6 -0
- data/lib/active_storage/previewer/mupdf_previewer.rb +3 -3
- data/lib/active_storage/previewer/poppler_pdf_previewer.rb +3 -3
- data/lib/active_storage/previewer/video_previewer.rb +17 -10
- data/lib/active_storage/previewer.rb +34 -14
- data/lib/active_storage/reflection.rb +64 -0
- data/lib/active_storage/service/azure_storage_service.rb +65 -44
- data/lib/active_storage/service/configurator.rb +6 -2
- data/lib/active_storage/service/disk_service.rb +57 -44
- data/lib/active_storage/service/gcs_service.rb +68 -64
- data/lib/active_storage/service/mirror_service.rb +31 -7
- data/lib/active_storage/service/registry.rb +32 -0
- data/lib/active_storage/service/s3_service.rb +56 -24
- data/lib/active_storage/service.rb +44 -12
- data/lib/active_storage/transformers/image_processing_transformer.rb +45 -0
- data/lib/active_storage/transformers/transformer.rb +39 -0
- data/lib/active_storage.rb +31 -296
- data/lib/tasks/activestorage.rake +11 -0
- metadata +82 -16
- data/app/models/active_storage/filename/parameters.rb +0 -36
- data/lib/active_storage/attached/macros.rb +0 -110
- data/lib/active_storage/downloading.rb +0 -39
@@ -9,21 +9,28 @@ module ActiveStorage
|
|
9
9
|
# Wraps the Amazon Simple Storage Service (S3) as an Active Storage service.
|
10
10
|
# See ActiveStorage::Service for the generic API documentation that applies to all services.
|
11
11
|
class Service::S3Service < Service
|
12
|
-
attr_reader :client, :bucket
|
12
|
+
attr_reader :client, :bucket
|
13
|
+
attr_reader :multipart_upload_threshold, :upload_options
|
13
14
|
|
14
|
-
def initialize(bucket:, upload: {}, **options)
|
15
|
+
def initialize(bucket:, upload: {}, public: false, **options)
|
15
16
|
@client = Aws::S3::Resource.new(**options)
|
16
17
|
@bucket = @client.bucket(bucket)
|
17
18
|
|
19
|
+
@multipart_upload_threshold = upload.delete(:multipart_threshold) || 100.megabytes
|
20
|
+
@public = public
|
21
|
+
|
18
22
|
@upload_options = upload
|
23
|
+
@upload_options[:acl] = "public-read" if public?
|
19
24
|
end
|
20
25
|
|
21
|
-
def upload(key, io, checksum: nil, **)
|
26
|
+
def upload(key, io, checksum: nil, filename: nil, content_type: nil, disposition: nil, **)
|
22
27
|
instrument :upload, key: key, checksum: checksum do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
content_disposition = content_disposition_with(filename: filename, type: disposition) if disposition && filename
|
29
|
+
|
30
|
+
if io.size < multipart_upload_threshold
|
31
|
+
upload_with_single_part key, io, checksum: checksum, content_type: content_type, content_disposition: content_disposition
|
32
|
+
else
|
33
|
+
upload_with_multipart key, io, content_type: content_type, content_disposition: content_disposition
|
27
34
|
end
|
28
35
|
end
|
29
36
|
end
|
@@ -36,13 +43,17 @@ module ActiveStorage
|
|
36
43
|
else
|
37
44
|
instrument :download, key: key do
|
38
45
|
object_for(key).get.body.string.force_encoding(Encoding::BINARY)
|
46
|
+
rescue Aws::S3::Errors::NoSuchKey
|
47
|
+
raise ActiveStorage::FileNotFoundError
|
39
48
|
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
43
52
|
def download_chunk(key, range)
|
44
53
|
instrument :download_chunk, key: key, range: range do
|
45
|
-
object_for(key).get(range: "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body.
|
54
|
+
object_for(key).get(range: "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body.string.force_encoding(Encoding::BINARY)
|
55
|
+
rescue Aws::S3::Errors::NoSuchKey
|
56
|
+
raise ActiveStorage::FileNotFoundError
|
46
57
|
end
|
47
58
|
end
|
48
59
|
|
@@ -66,23 +77,11 @@ module ActiveStorage
|
|
66
77
|
end
|
67
78
|
end
|
68
79
|
|
69
|
-
def url(key, expires_in:, filename:, disposition:, content_type:)
|
70
|
-
instrument :url, key: key do |payload|
|
71
|
-
generated_url = object_for(key).presigned_url :get, expires_in: expires_in.to_i,
|
72
|
-
response_content_disposition: content_disposition_with(type: disposition, filename: filename),
|
73
|
-
response_content_type: content_type
|
74
|
-
|
75
|
-
payload[:url] = generated_url
|
76
|
-
|
77
|
-
generated_url
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
80
|
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
|
82
81
|
instrument :url, key: key do |payload|
|
83
82
|
generated_url = object_for(key).presigned_url :put, expires_in: expires_in.to_i,
|
84
83
|
content_type: content_type, content_length: content_length, content_md5: checksum,
|
85
|
-
whitelist_headers: [
|
84
|
+
whitelist_headers: ["content-length"], **upload_options
|
86
85
|
|
87
86
|
payload[:url] = generated_url
|
88
87
|
|
@@ -90,11 +89,42 @@ module ActiveStorage
|
|
90
89
|
end
|
91
90
|
end
|
92
91
|
|
93
|
-
def headers_for_direct_upload(key, content_type:, checksum:, **)
|
94
|
-
|
92
|
+
def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, **)
|
93
|
+
content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
|
94
|
+
|
95
|
+
{ "Content-Type" => content_type, "Content-MD5" => checksum, "Content-Disposition" => content_disposition }
|
95
96
|
end
|
96
97
|
|
97
98
|
private
|
99
|
+
def private_url(key, expires_in:, filename:, disposition:, content_type:, **)
|
100
|
+
object_for(key).presigned_url :get, expires_in: expires_in.to_i,
|
101
|
+
response_content_disposition: content_disposition_with(type: disposition, filename: filename),
|
102
|
+
response_content_type: content_type
|
103
|
+
end
|
104
|
+
|
105
|
+
def public_url(key, **)
|
106
|
+
object_for(key).public_url
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
MAXIMUM_UPLOAD_PARTS_COUNT = 10000
|
111
|
+
MINIMUM_UPLOAD_PART_SIZE = 5.megabytes
|
112
|
+
|
113
|
+
def upload_with_single_part(key, io, checksum: nil, content_type: nil, content_disposition: nil)
|
114
|
+
object_for(key).put(body: io, content_md5: checksum, content_type: content_type, content_disposition: content_disposition, **upload_options)
|
115
|
+
rescue Aws::S3::Errors::BadDigest
|
116
|
+
raise ActiveStorage::IntegrityError
|
117
|
+
end
|
118
|
+
|
119
|
+
def upload_with_multipart(key, io, content_type: nil, content_disposition: nil)
|
120
|
+
part_size = [ io.size.fdiv(MAXIMUM_UPLOAD_PARTS_COUNT).ceil, MINIMUM_UPLOAD_PART_SIZE ].max
|
121
|
+
|
122
|
+
object_for(key).upload_stream(content_type: content_type, content_disposition: content_disposition, part_size: part_size, **upload_options) do |out|
|
123
|
+
IO.copy_stream(io, out)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
98
128
|
def object_for(key)
|
99
129
|
bucket.object(key)
|
100
130
|
end
|
@@ -106,8 +136,10 @@ module ActiveStorage
|
|
106
136
|
chunk_size = 5.megabytes
|
107
137
|
offset = 0
|
108
138
|
|
139
|
+
raise ActiveStorage::FileNotFoundError unless object.exists?
|
140
|
+
|
109
141
|
while offset < object.content_length
|
110
|
-
yield object.get(range: "bytes=#{offset}-#{offset + chunk_size - 1}").body.
|
142
|
+
yield object.get(range: "bytes=#{offset}-#{offset + chunk_size - 1}").body.string.force_encoding(Encoding::BINARY)
|
111
143
|
offset += chunk_size
|
112
144
|
end
|
113
145
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_storage/log_subscriber"
|
4
|
+
require "active_storage/downloader"
|
5
|
+
require "action_dispatch"
|
6
|
+
require "action_dispatch/http/content_disposition"
|
4
7
|
|
5
8
|
module ActiveStorage
|
6
|
-
class IntegrityError < StandardError; end
|
7
|
-
|
8
9
|
# Abstract class serving as an interface for concrete services.
|
9
10
|
#
|
10
11
|
# The available services are:
|
@@ -40,8 +41,7 @@ module ActiveStorage
|
|
40
41
|
class Service
|
41
42
|
extend ActiveSupport::Autoload
|
42
43
|
autoload :Configurator
|
43
|
-
|
44
|
-
class_attribute :url_expires_in, default: 5.minutes
|
44
|
+
attr_accessor :name
|
45
45
|
|
46
46
|
class << self
|
47
47
|
# Configure an Active Storage service by name from a set of configurations,
|
@@ -57,8 +57,10 @@ module ActiveStorage
|
|
57
57
|
# Passes the configurator and all of the service's config as keyword args.
|
58
58
|
#
|
59
59
|
# See MirrorService for an example.
|
60
|
-
def build(configurator:, service: nil, **service_config) #:nodoc:
|
61
|
-
new(**service_config)
|
60
|
+
def build(configurator:, name:, service: nil, **service_config) #:nodoc:
|
61
|
+
new(**service_config).tap do |service_instance|
|
62
|
+
service_instance.name = name
|
63
|
+
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -84,6 +86,10 @@ module ActiveStorage
|
|
84
86
|
raise NotImplementedError
|
85
87
|
end
|
86
88
|
|
89
|
+
def open(*args, **options, &block)
|
90
|
+
ActiveStorage::Downloader.new(self).open(*args, **options, &block)
|
91
|
+
end
|
92
|
+
|
87
93
|
# Delete the file at the +key+.
|
88
94
|
def delete(key)
|
89
95
|
raise NotImplementedError
|
@@ -99,11 +105,23 @@ module ActiveStorage
|
|
99
105
|
raise NotImplementedError
|
100
106
|
end
|
101
107
|
|
102
|
-
# Returns
|
103
|
-
#
|
104
|
-
# +filename+, and +content_type+ that you wish the file to be served with on request.
|
105
|
-
|
106
|
-
|
108
|
+
# Returns the URL for the file at the +key+. This returns a permanent URL for public files, and returns a
|
109
|
+
# short-lived URL for private files. For private files you can provide the +disposition+ (+:inline+ or +:attachment+),
|
110
|
+
# +filename+, and +content_type+ that you wish the file to be served with on request. Additionally, you can also provide
|
111
|
+
# the amount of seconds the URL will be valid for, specified in +expires_in+.
|
112
|
+
def url(key, **options)
|
113
|
+
instrument :url, key: key do |payload|
|
114
|
+
generated_url =
|
115
|
+
if public?
|
116
|
+
public_url(key, **options)
|
117
|
+
else
|
118
|
+
private_url(key, **options)
|
119
|
+
end
|
120
|
+
|
121
|
+
payload[:url] = generated_url
|
122
|
+
|
123
|
+
generated_url
|
124
|
+
end
|
107
125
|
end
|
108
126
|
|
109
127
|
# Returns a signed, temporary URL that a direct upload file can be PUT to on the +key+.
|
@@ -119,7 +137,20 @@ module ActiveStorage
|
|
119
137
|
{}
|
120
138
|
end
|
121
139
|
|
140
|
+
def public?
|
141
|
+
@public
|
142
|
+
end
|
143
|
+
|
122
144
|
private
|
145
|
+
def private_url(key, expires_in:, filename:, disposition:, content_type:, **)
|
146
|
+
raise NotImplementedError
|
147
|
+
end
|
148
|
+
|
149
|
+
def public_url(key, **)
|
150
|
+
raise NotImplementedError
|
151
|
+
end
|
152
|
+
|
153
|
+
|
123
154
|
def instrument(operation, payload = {}, &block)
|
124
155
|
ActiveSupport::Notifications.instrument(
|
125
156
|
"service_#{operation}.active_storage",
|
@@ -132,7 +163,8 @@ module ActiveStorage
|
|
132
163
|
end
|
133
164
|
|
134
165
|
def content_disposition_with(type: "inline", filename:)
|
135
|
-
(type.to_s.presence_in(%w( attachment inline )) || "inline")
|
166
|
+
disposition = (type.to_s.presence_in(%w( attachment inline )) || "inline")
|
167
|
+
ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: filename.sanitized)
|
136
168
|
end
|
137
169
|
end
|
138
170
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "image_processing"
|
5
|
+
rescue LoadError
|
6
|
+
raise LoadError, <<~ERROR.squish
|
7
|
+
Generating image variants require the image_processing gem.
|
8
|
+
Please add `gem 'image_processing', '~> 1.2'` to your Gemfile.
|
9
|
+
ERROR
|
10
|
+
end
|
11
|
+
|
12
|
+
module ActiveStorage
|
13
|
+
module Transformers
|
14
|
+
class ImageProcessingTransformer < Transformer
|
15
|
+
private
|
16
|
+
def process(file, format:)
|
17
|
+
processor.
|
18
|
+
source(file).
|
19
|
+
loader(page: 0).
|
20
|
+
convert(format).
|
21
|
+
apply(operations).
|
22
|
+
call
|
23
|
+
end
|
24
|
+
|
25
|
+
def processor
|
26
|
+
ImageProcessing.const_get(ActiveStorage.variant_processor.to_s.camelize)
|
27
|
+
end
|
28
|
+
|
29
|
+
def operations
|
30
|
+
transformations.each_with_object([]) do |(name, argument), list|
|
31
|
+
if name.to_s == "combine_options"
|
32
|
+
raise ArgumentError, <<~ERROR.squish
|
33
|
+
Active Storage's ImageProcessing transformer doesn't support :combine_options,
|
34
|
+
as it always generates a single ImageMagick command.
|
35
|
+
ERROR
|
36
|
+
end
|
37
|
+
|
38
|
+
if argument.present?
|
39
|
+
list << [ name, argument ]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveStorage
|
4
|
+
module Transformers
|
5
|
+
# A Transformer applies a set of transformations to an image.
|
6
|
+
#
|
7
|
+
# The following concrete subclasses are included in Active Storage:
|
8
|
+
#
|
9
|
+
# * ActiveStorage::Transformers::ImageProcessingTransformer:
|
10
|
+
# backed by ImageProcessing, a common interface for MiniMagick and ruby-vips
|
11
|
+
class Transformer
|
12
|
+
attr_reader :transformations
|
13
|
+
|
14
|
+
def initialize(transformations)
|
15
|
+
@transformations = transformations
|
16
|
+
end
|
17
|
+
|
18
|
+
# Applies the transformations to the source image in +file+, producing a target image in the
|
19
|
+
# specified +format+. Yields an open Tempfile containing the target image. Closes and unlinks
|
20
|
+
# the output tempfile after yielding to the given block. Returns the result of the block.
|
21
|
+
def transform(file, format:)
|
22
|
+
output = process(file, format: format)
|
23
|
+
|
24
|
+
begin
|
25
|
+
yield output
|
26
|
+
ensure
|
27
|
+
output.close!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
# Returns an open Tempfile containing a transformed image in the given +format+.
|
33
|
+
# All subclasses implement this method.
|
34
|
+
def process(file, format:) #:doc:
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/active_storage.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2017-
|
4
|
+
# Copyright (c) 2017-2020 David Heinemeier Hansson, Basecamp
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -26,6 +26,7 @@
|
|
26
26
|
require "active_record"
|
27
27
|
require "active_support"
|
28
28
|
require "active_support/rails"
|
29
|
+
require "active_support/core_ext/numeric/time"
|
29
30
|
|
30
31
|
require "active_storage/version"
|
31
32
|
require "active_storage/errors"
|
@@ -42,302 +43,36 @@ module ActiveStorage
|
|
42
43
|
|
43
44
|
mattr_accessor :logger
|
44
45
|
mattr_accessor :verifier
|
45
|
-
mattr_accessor :
|
46
|
+
mattr_accessor :variant_processor, default: :mini_magick
|
47
|
+
|
48
|
+
mattr_accessor :queues, default: {}
|
49
|
+
|
46
50
|
mattr_accessor :previewers, default: []
|
47
|
-
mattr_accessor :analyzers,
|
51
|
+
mattr_accessor :analyzers, default: []
|
52
|
+
|
48
53
|
mattr_accessor :paths, default: {}
|
49
|
-
|
54
|
+
|
55
|
+
mattr_accessor :variable_content_types, default: []
|
56
|
+
mattr_accessor :web_image_content_types, default: []
|
57
|
+
mattr_accessor :binary_content_type, default: "application/octet-stream"
|
50
58
|
mattr_accessor :content_types_to_serve_as_binary, default: []
|
51
|
-
mattr_accessor :content_types_allowed_inline,
|
52
|
-
|
53
|
-
mattr_accessor :
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
"backdrop",
|
71
|
-
"background",
|
72
|
-
"bench",
|
73
|
-
"bias",
|
74
|
-
"bilateral_blur",
|
75
|
-
"black_point_compensation",
|
76
|
-
"black_threshold",
|
77
|
-
"blend",
|
78
|
-
"blue_primary",
|
79
|
-
"blue_shift",
|
80
|
-
"blur",
|
81
|
-
"border",
|
82
|
-
"bordercolor",
|
83
|
-
"borderwidth",
|
84
|
-
"brightness_contrast",
|
85
|
-
"cache",
|
86
|
-
"canny",
|
87
|
-
"caption",
|
88
|
-
"channel",
|
89
|
-
"channel_fx",
|
90
|
-
"charcoal",
|
91
|
-
"chop",
|
92
|
-
"clahe",
|
93
|
-
"clamp",
|
94
|
-
"clip",
|
95
|
-
"clip_path",
|
96
|
-
"clone",
|
97
|
-
"clut",
|
98
|
-
"coalesce",
|
99
|
-
"colorize",
|
100
|
-
"colormap",
|
101
|
-
"color_matrix",
|
102
|
-
"colors",
|
103
|
-
"colorspace",
|
104
|
-
"colourspace",
|
105
|
-
"color_threshold",
|
106
|
-
"combine",
|
107
|
-
"combine_options",
|
108
|
-
"comment",
|
109
|
-
"compare",
|
110
|
-
"complex",
|
111
|
-
"compose",
|
112
|
-
"composite",
|
113
|
-
"compress",
|
114
|
-
"connected_components",
|
115
|
-
"contrast",
|
116
|
-
"contrast_stretch",
|
117
|
-
"convert",
|
118
|
-
"convolve",
|
119
|
-
"copy",
|
120
|
-
"crop",
|
121
|
-
"cycle",
|
122
|
-
"deconstruct",
|
123
|
-
"define",
|
124
|
-
"delay",
|
125
|
-
"delete",
|
126
|
-
"density",
|
127
|
-
"depth",
|
128
|
-
"descend",
|
129
|
-
"deskew",
|
130
|
-
"despeckle",
|
131
|
-
"direction",
|
132
|
-
"displace",
|
133
|
-
"dispose",
|
134
|
-
"dissimilarity_threshold",
|
135
|
-
"dissolve",
|
136
|
-
"distort",
|
137
|
-
"dither",
|
138
|
-
"draw",
|
139
|
-
"duplicate",
|
140
|
-
"edge",
|
141
|
-
"emboss",
|
142
|
-
"encoding",
|
143
|
-
"endian",
|
144
|
-
"enhance",
|
145
|
-
"equalize",
|
146
|
-
"evaluate",
|
147
|
-
"evaluate_sequence",
|
148
|
-
"extent",
|
149
|
-
"extract",
|
150
|
-
"family",
|
151
|
-
"features",
|
152
|
-
"fft",
|
153
|
-
"fill",
|
154
|
-
"filter",
|
155
|
-
"flatten",
|
156
|
-
"flip",
|
157
|
-
"floodfill",
|
158
|
-
"flop",
|
159
|
-
"font",
|
160
|
-
"foreground",
|
161
|
-
"format",
|
162
|
-
"frame",
|
163
|
-
"function",
|
164
|
-
"fuzz",
|
165
|
-
"fx",
|
166
|
-
"gamma",
|
167
|
-
"gaussian_blur",
|
168
|
-
"geometry",
|
169
|
-
"gravity",
|
170
|
-
"grayscale",
|
171
|
-
"green_primary",
|
172
|
-
"hald_clut",
|
173
|
-
"highlight_color",
|
174
|
-
"hough_lines",
|
175
|
-
"iconGeometry",
|
176
|
-
"iconic",
|
177
|
-
"identify",
|
178
|
-
"ift",
|
179
|
-
"illuminant",
|
180
|
-
"immutable",
|
181
|
-
"implode",
|
182
|
-
"insert",
|
183
|
-
"intensity",
|
184
|
-
"intent",
|
185
|
-
"interlace",
|
186
|
-
"interline_spacing",
|
187
|
-
"interpolate",
|
188
|
-
"interpolative_resize",
|
189
|
-
"interword_spacing",
|
190
|
-
"kerning",
|
191
|
-
"kmeans",
|
192
|
-
"kuwahara",
|
193
|
-
"label",
|
194
|
-
"lat",
|
195
|
-
"layers",
|
196
|
-
"level",
|
197
|
-
"level_colors",
|
198
|
-
"limit",
|
199
|
-
"limits",
|
200
|
-
"linear_stretch",
|
201
|
-
"linewidth",
|
202
|
-
"liquid_rescale",
|
203
|
-
"list",
|
204
|
-
"loader",
|
205
|
-
"log",
|
206
|
-
"loop",
|
207
|
-
"lowlight_color",
|
208
|
-
"magnify",
|
209
|
-
"map",
|
210
|
-
"mattecolor",
|
211
|
-
"median",
|
212
|
-
"mean_shift",
|
213
|
-
"metric",
|
214
|
-
"mode",
|
215
|
-
"modulate",
|
216
|
-
"moments",
|
217
|
-
"monitor",
|
218
|
-
"monochrome",
|
219
|
-
"morph",
|
220
|
-
"morphology",
|
221
|
-
"mosaic",
|
222
|
-
"motion_blur",
|
223
|
-
"name",
|
224
|
-
"negate",
|
225
|
-
"noise",
|
226
|
-
"normalize",
|
227
|
-
"opaque",
|
228
|
-
"ordered_dither",
|
229
|
-
"orient",
|
230
|
-
"page",
|
231
|
-
"paint",
|
232
|
-
"pause",
|
233
|
-
"perceptible",
|
234
|
-
"ping",
|
235
|
-
"pointsize",
|
236
|
-
"polaroid",
|
237
|
-
"poly",
|
238
|
-
"posterize",
|
239
|
-
"precision",
|
240
|
-
"preview",
|
241
|
-
"process",
|
242
|
-
"quality",
|
243
|
-
"quantize",
|
244
|
-
"quiet",
|
245
|
-
"radial_blur",
|
246
|
-
"raise",
|
247
|
-
"random_threshold",
|
248
|
-
"range_threshold",
|
249
|
-
"red_primary",
|
250
|
-
"regard_warnings",
|
251
|
-
"region",
|
252
|
-
"remote",
|
253
|
-
"render",
|
254
|
-
"repage",
|
255
|
-
"resample",
|
256
|
-
"resize",
|
257
|
-
"resize_to_fill",
|
258
|
-
"resize_to_fit",
|
259
|
-
"resize_to_limit",
|
260
|
-
"resize_and_pad",
|
261
|
-
"respect_parentheses",
|
262
|
-
"reverse",
|
263
|
-
"roll",
|
264
|
-
"rotate",
|
265
|
-
"sample",
|
266
|
-
"sampling_factor",
|
267
|
-
"saver",
|
268
|
-
"scale",
|
269
|
-
"scene",
|
270
|
-
"screen",
|
271
|
-
"seed",
|
272
|
-
"segment",
|
273
|
-
"selective_blur",
|
274
|
-
"separate",
|
275
|
-
"sepia_tone",
|
276
|
-
"shade",
|
277
|
-
"shadow",
|
278
|
-
"shared_memory",
|
279
|
-
"sharpen",
|
280
|
-
"shave",
|
281
|
-
"shear",
|
282
|
-
"sigmoidal_contrast",
|
283
|
-
"silent",
|
284
|
-
"similarity_threshold",
|
285
|
-
"size",
|
286
|
-
"sketch",
|
287
|
-
"smush",
|
288
|
-
"snaps",
|
289
|
-
"solarize",
|
290
|
-
"sort_pixels",
|
291
|
-
"sparse_color",
|
292
|
-
"splice",
|
293
|
-
"spread",
|
294
|
-
"statistic",
|
295
|
-
"stegano",
|
296
|
-
"stereo",
|
297
|
-
"storage_type",
|
298
|
-
"stretch",
|
299
|
-
"strip",
|
300
|
-
"stroke",
|
301
|
-
"strokewidth",
|
302
|
-
"style",
|
303
|
-
"subimage_search",
|
304
|
-
"swap",
|
305
|
-
"swirl",
|
306
|
-
"synchronize",
|
307
|
-
"taint",
|
308
|
-
"text_font",
|
309
|
-
"threshold",
|
310
|
-
"thumbnail",
|
311
|
-
"tile_offset",
|
312
|
-
"tint",
|
313
|
-
"title",
|
314
|
-
"transform",
|
315
|
-
"transparent",
|
316
|
-
"transparent_color",
|
317
|
-
"transpose",
|
318
|
-
"transverse",
|
319
|
-
"treedepth",
|
320
|
-
"trim",
|
321
|
-
"type",
|
322
|
-
"undercolor",
|
323
|
-
"unique_colors",
|
324
|
-
"units",
|
325
|
-
"unsharp",
|
326
|
-
"update",
|
327
|
-
"valid_image",
|
328
|
-
"view",
|
329
|
-
"vignette",
|
330
|
-
"virtual_pixel",
|
331
|
-
"visual",
|
332
|
-
"watermark",
|
333
|
-
"wave",
|
334
|
-
"wavelet_denoise",
|
335
|
-
"weight",
|
336
|
-
"white_balance",
|
337
|
-
"white_point",
|
338
|
-
"white_threshold",
|
339
|
-
"window",
|
340
|
-
"window_group",
|
341
|
-
]
|
342
|
-
mattr_accessor :unsupported_image_processing_arguments
|
59
|
+
mattr_accessor :content_types_allowed_inline, default: []
|
60
|
+
|
61
|
+
mattr_accessor :service_urls_expire_in, default: 5.minutes
|
62
|
+
|
63
|
+
mattr_accessor :routes_prefix, default: "/rails/active_storage"
|
64
|
+
mattr_accessor :draw_routes, default: true
|
65
|
+
mattr_accessor :resolve_model_to_route, default: :rails_storage_redirect
|
66
|
+
|
67
|
+
mattr_accessor :replace_on_assign_to_many, default: false
|
68
|
+
mattr_accessor :track_variants, default: false
|
69
|
+
|
70
|
+
mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
|
71
|
+
|
72
|
+
module Transformers
|
73
|
+
extend ActiveSupport::Autoload
|
74
|
+
|
75
|
+
autoload :Transformer
|
76
|
+
autoload :ImageProcessingTransformer
|
77
|
+
end
|
343
78
|
end
|
@@ -12,4 +12,15 @@ namespace :active_storage do
|
|
12
12
|
Rake::Task["app:active_storage:install:migrations"].invoke
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
# desc "Copy over the migrations needed to the application upgrading"
|
17
|
+
task update: :environment do
|
18
|
+
ENV["MIGRATIONS_PATH"] = "db/update_migrate"
|
19
|
+
|
20
|
+
if Rake::Task.task_defined?("active_storage:install")
|
21
|
+
Rake::Task["active_storage:install"].invoke
|
22
|
+
else
|
23
|
+
Rake::Task["app:active_storage:install"].invoke
|
24
|
+
end
|
25
|
+
end
|
15
26
|
end
|