activestorage 5.2.4.1 → 6.0.1

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.

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +145 -61
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +9 -6
  5. data/app/assets/javascripts/activestorage.js +4 -1
  6. data/app/controllers/active_storage/base_controller.rb +3 -5
  7. data/app/controllers/active_storage/blobs_controller.rb +1 -1
  8. data/app/controllers/active_storage/disk_controller.rb +5 -2
  9. data/app/controllers/active_storage/representations_controller.rb +1 -1
  10. data/app/controllers/concerns/active_storage/set_current.rb +15 -0
  11. data/app/javascript/activestorage/blob_record.js +6 -1
  12. data/app/jobs/active_storage/analyze_job.rb +5 -0
  13. data/app/jobs/active_storage/base_job.rb +0 -1
  14. data/app/jobs/active_storage/purge_job.rb +3 -0
  15. data/app/models/active_storage/attachment.rb +20 -9
  16. data/app/models/active_storage/blob.rb +84 -31
  17. data/app/models/active_storage/blob/representable.rb +5 -5
  18. data/app/models/active_storage/filename.rb +0 -6
  19. data/app/models/active_storage/preview.rb +3 -3
  20. data/app/models/active_storage/variant.rb +51 -52
  21. data/app/models/active_storage/variation.rb +24 -33
  22. data/config/routes.rb +13 -12
  23. data/db/update_migrate/20180723000244_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.rb +9 -0
  24. data/lib/active_storage.rb +26 -6
  25. data/lib/active_storage/analyzer.rb +9 -4
  26. data/lib/active_storage/analyzer/image_analyzer.rb +11 -4
  27. data/lib/active_storage/analyzer/video_analyzer.rb +3 -5
  28. data/lib/active_storage/attached.rb +7 -22
  29. data/lib/active_storage/attached/changes.rb +16 -0
  30. data/lib/active_storage/attached/changes/create_many.rb +46 -0
  31. data/lib/active_storage/attached/changes/create_one.rb +69 -0
  32. data/lib/active_storage/attached/changes/create_one_of_many.rb +10 -0
  33. data/lib/active_storage/attached/changes/delete_many.rb +27 -0
  34. data/lib/active_storage/attached/changes/delete_one.rb +19 -0
  35. data/lib/active_storage/attached/many.rb +16 -10
  36. data/lib/active_storage/attached/model.rb +147 -0
  37. data/lib/active_storage/attached/one.rb +16 -19
  38. data/lib/active_storage/downloader.rb +43 -0
  39. data/lib/active_storage/downloading.rb +8 -0
  40. data/lib/active_storage/engine.rb +43 -6
  41. data/lib/active_storage/errors.rb +22 -3
  42. data/lib/active_storage/gem_version.rb +4 -4
  43. data/lib/active_storage/previewer.rb +21 -11
  44. data/lib/active_storage/previewer/poppler_pdf_previewer.rb +2 -2
  45. data/lib/active_storage/previewer/video_previewer.rb +2 -3
  46. data/lib/active_storage/reflection.rb +64 -0
  47. data/lib/active_storage/service.rb +9 -6
  48. data/lib/active_storage/service/azure_storage_service.rb +30 -14
  49. data/lib/active_storage/service/configurator.rb +3 -1
  50. data/lib/active_storage/service/disk_service.rb +19 -11
  51. data/lib/active_storage/service/gcs_service.rb +49 -47
  52. data/lib/active_storage/service/s3_service.rb +10 -6
  53. data/lib/active_storage/transformers/image_processing_transformer.rb +39 -0
  54. data/lib/active_storage/transformers/mini_magick_transformer.rb +38 -0
  55. data/lib/active_storage/transformers/transformer.rb +42 -0
  56. data/lib/tasks/activestorage.rake +7 -0
  57. metadata +41 -12
  58. data/app/models/active_storage/filename/parameters.rb +0 -36
  59. data/lib/active_storage/attached/macros.rb +0 -110
@@ -16,13 +16,11 @@ module ActiveStorage
16
16
  @upload_options = upload
17
17
  end
18
18
 
19
- def upload(key, io, checksum: nil, **)
19
+ def upload(key, io, checksum: nil, content_type: nil, **)
20
20
  instrument :upload, key: key, checksum: checksum do
21
- begin
22
- object_for(key).put(upload_options.merge(body: io, content_md5: checksum))
23
- rescue Aws::S3::Errors::BadDigest
24
- raise ActiveStorage::IntegrityError
25
- end
21
+ object_for(key).put(upload_options.merge(body: io, content_md5: checksum, content_type: content_type))
22
+ rescue Aws::S3::Errors::BadDigest
23
+ raise ActiveStorage::IntegrityError
26
24
  end
27
25
  end
28
26
 
@@ -34,6 +32,8 @@ module ActiveStorage
34
32
  else
35
33
  instrument :download, key: key do
36
34
  object_for(key).get.body.string.force_encoding(Encoding::BINARY)
35
+ rescue Aws::S3::Errors::NoSuchKey
36
+ raise ActiveStorage::FileNotFoundError
37
37
  end
38
38
  end
39
39
  end
@@ -41,6 +41,8 @@ module ActiveStorage
41
41
  def download_chunk(key, range)
42
42
  instrument :download_chunk, key: key, range: range do
43
43
  object_for(key).get(range: "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body.read.force_encoding(Encoding::BINARY)
44
+ rescue Aws::S3::Errors::NoSuchKey
45
+ raise ActiveStorage::FileNotFoundError
44
46
  end
45
47
  end
46
48
 
@@ -103,6 +105,8 @@ module ActiveStorage
103
105
  chunk_size = 5.megabytes
104
106
  offset = 0
105
107
 
108
+ raise ActiveStorage::FileNotFoundError unless object.exists?
109
+
106
110
  while offset < object.content_length
107
111
  yield object.get(range: "bytes=#{offset}-#{offset + chunk_size - 1}").body.read.force_encoding(Encoding::BINARY)
108
112
  offset += chunk_size
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "image_processing"
4
+
5
+ module ActiveStorage
6
+ module Transformers
7
+ class ImageProcessingTransformer < Transformer
8
+ private
9
+ def process(file, format:)
10
+ processor.
11
+ source(file).
12
+ loader(page: 0).
13
+ convert(format).
14
+ apply(operations).
15
+ call
16
+ end
17
+
18
+ def processor
19
+ ImageProcessing.const_get(ActiveStorage.variant_processor.to_s.camelize)
20
+ end
21
+
22
+ def operations
23
+ transformations.each_with_object([]) do |(name, argument), list|
24
+ if name.to_s == "combine_options"
25
+ ActiveSupport::Deprecation.warn <<~WARNING.squish
26
+ Active Storage's ImageProcessing transformer doesn't support :combine_options,
27
+ as it always generates a single ImageMagick command. Passing :combine_options will
28
+ not be supported in Rails 6.1.
29
+ WARNING
30
+
31
+ list.concat argument.keep_if { |key, value| value.present? }.to_a
32
+ elsif argument.present?
33
+ list << [ name, argument ]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mini_magick"
4
+
5
+ module ActiveStorage
6
+ module Transformers
7
+ class MiniMagickTransformer < Transformer
8
+ private
9
+ def process(file, format:)
10
+ image = MiniMagick::Image.new(file.path, file)
11
+
12
+ transformations.each do |name, argument_or_subtransformations|
13
+ image.mogrify do |command|
14
+ if name.to_s == "combine_options"
15
+ argument_or_subtransformations.each do |subtransformation_name, subtransformation_argument|
16
+ pass_transform_argument(command, subtransformation_name, subtransformation_argument)
17
+ end
18
+ else
19
+ pass_transform_argument(command, name, argument_or_subtransformations)
20
+ end
21
+ end
22
+ end
23
+
24
+ image.format(format) if format
25
+
26
+ image.tempfile.tap(&:open)
27
+ end
28
+
29
+ def pass_transform_argument(command, method, argument)
30
+ if argument == true
31
+ command.public_send(method)
32
+ elsif argument.present?
33
+ command.public_send(method, argument)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
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
+ #
12
+ # * ActiveStorage::Transformers::MiniMagickTransformer:
13
+ # backed by MiniMagick, a wrapper around the ImageMagick CLI
14
+ class Transformer
15
+ attr_reader :transformations
16
+
17
+ def initialize(transformations)
18
+ @transformations = transformations
19
+ end
20
+
21
+ # Applies the transformations to the source image in +file+, producing a target image in the
22
+ # specified +format+. Yields an open Tempfile containing the target image. Closes and unlinks
23
+ # the output tempfile after yielding to the given block. Returns the result of the block.
24
+ def transform(file, format:)
25
+ output = process(file, format: format)
26
+
27
+ begin
28
+ yield output
29
+ ensure
30
+ output.close!
31
+ end
32
+ end
33
+
34
+ private
35
+ # Returns an open Tempfile containing a transformed image in the given +format+.
36
+ # All subclasses implement this method.
37
+ def process(file, format:) #:doc:
38
+ raise NotImplementedError
39
+ end
40
+ end
41
+ end
42
+ end
@@ -12,4 +12,11 @@ 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
+ Rake::Task["active_storage:install"].invoke
21
+ end
15
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activestorage
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.4.1
4
+ version: 6.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-18 00:00:00.000000000 Z
11
+ date: 2019-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 5.2.4.1
19
+ version: 6.0.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 5.2.4.1
26
+ version: 6.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: activejob
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 6.0.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: activerecord
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - '='
32
46
  - !ruby/object:Gem::Version
33
- version: 5.2.4.1
47
+ version: 6.0.1
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - '='
39
53
  - !ruby/object:Gem::Version
40
- version: 5.2.4.1
54
+ version: 6.0.1
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: marcel
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -68,6 +82,7 @@ files:
68
82
  - app/controllers/active_storage/disk_controller.rb
69
83
  - app/controllers/active_storage/representations_controller.rb
70
84
  - app/controllers/concerns/active_storage/set_blob.rb
85
+ - app/controllers/concerns/active_storage/set_current.rb
71
86
  - app/javascript/activestorage/blob_record.js
72
87
  - app/javascript/activestorage/blob_upload.js
73
88
  - app/javascript/activestorage/direct_upload.js
@@ -87,21 +102,28 @@ files:
87
102
  - app/models/active_storage/blob/representable.rb
88
103
  - app/models/active_storage/current.rb
89
104
  - app/models/active_storage/filename.rb
90
- - app/models/active_storage/filename/parameters.rb
91
105
  - app/models/active_storage/preview.rb
92
106
  - app/models/active_storage/variant.rb
93
107
  - app/models/active_storage/variation.rb
94
108
  - config/routes.rb
95
109
  - db/migrate/20170806125915_create_active_storage_tables.rb
110
+ - db/update_migrate/20180723000244_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.rb
96
111
  - lib/active_storage.rb
97
112
  - lib/active_storage/analyzer.rb
98
113
  - lib/active_storage/analyzer/image_analyzer.rb
99
114
  - lib/active_storage/analyzer/null_analyzer.rb
100
115
  - lib/active_storage/analyzer/video_analyzer.rb
101
116
  - lib/active_storage/attached.rb
102
- - lib/active_storage/attached/macros.rb
117
+ - lib/active_storage/attached/changes.rb
118
+ - lib/active_storage/attached/changes/create_many.rb
119
+ - lib/active_storage/attached/changes/create_one.rb
120
+ - lib/active_storage/attached/changes/create_one_of_many.rb
121
+ - lib/active_storage/attached/changes/delete_many.rb
122
+ - lib/active_storage/attached/changes/delete_one.rb
103
123
  - lib/active_storage/attached/many.rb
124
+ - lib/active_storage/attached/model.rb
104
125
  - lib/active_storage/attached/one.rb
126
+ - lib/active_storage/downloader.rb
105
127
  - lib/active_storage/downloading.rb
106
128
  - lib/active_storage/engine.rb
107
129
  - lib/active_storage/errors.rb
@@ -111,6 +133,7 @@ files:
111
133
  - lib/active_storage/previewer/mupdf_previewer.rb
112
134
  - lib/active_storage/previewer/poppler_pdf_previewer.rb
113
135
  - lib/active_storage/previewer/video_previewer.rb
136
+ - lib/active_storage/reflection.rb
114
137
  - lib/active_storage/service.rb
115
138
  - lib/active_storage/service/azure_storage_service.rb
116
139
  - lib/active_storage/service/configurator.rb
@@ -118,14 +141,20 @@ files:
118
141
  - lib/active_storage/service/gcs_service.rb
119
142
  - lib/active_storage/service/mirror_service.rb
120
143
  - lib/active_storage/service/s3_service.rb
144
+ - lib/active_storage/transformers/image_processing_transformer.rb
145
+ - lib/active_storage/transformers/mini_magick_transformer.rb
146
+ - lib/active_storage/transformers/transformer.rb
121
147
  - lib/active_storage/version.rb
122
148
  - lib/tasks/activestorage.rake
123
- homepage: http://rubyonrails.org
149
+ homepage: https://rubyonrails.org
124
150
  licenses:
125
151
  - MIT
126
152
  metadata:
127
- source_code_uri: https://github.com/rails/rails/tree/v5.2.4.1/activestorage
128
- changelog_uri: https://github.com/rails/rails/blob/v5.2.4.1/activestorage/CHANGELOG.md
153
+ bug_tracker_uri: https://github.com/rails/rails/issues
154
+ changelog_uri: https://github.com/rails/rails/blob/v6.0.1/activestorage/CHANGELOG.md
155
+ documentation_uri: https://api.rubyonrails.org/v6.0.1/
156
+ mailing_list_uri: https://groups.google.com/forum/#!forum/rubyonrails-talk
157
+ source_code_uri: https://github.com/rails/rails/tree/v6.0.1/activestorage
129
158
  post_install_message:
130
159
  rdoc_options: []
131
160
  require_paths:
@@ -134,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
134
163
  requirements:
135
164
  - - ">="
136
165
  - !ruby/object:Gem::Version
137
- version: 2.2.2
166
+ version: 2.5.0
138
167
  required_rubygems_version: !ruby/object:Gem::Requirement
139
168
  requirements:
140
169
  - - ">="
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveStorage::Filename::Parameters #:nodoc:
4
- attr_reader :filename
5
-
6
- def initialize(filename)
7
- @filename = filename
8
- end
9
-
10
- def combined
11
- "#{ascii}; #{utf8}"
12
- end
13
-
14
- TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/
15
-
16
- def ascii
17
- 'filename="' + percent_escape(I18n.transliterate(filename.sanitized), TRADITIONAL_ESCAPED_CHAR) + '"'
18
- end
19
-
20
- RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/
21
-
22
- def utf8
23
- "filename*=UTF-8''" + percent_escape(filename.sanitized, RFC_5987_ESCAPED_CHAR)
24
- end
25
-
26
- def to_s
27
- combined
28
- end
29
-
30
- private
31
- def percent_escape(string, pattern)
32
- string.gsub(pattern) do |char|
33
- char.bytes.map { |byte| "%%%02X" % byte }.join
34
- end
35
- end
36
- end
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveStorage
4
- # Provides the class-level DSL for declaring that an Active Record model has attached blobs.
5
- module Attached::Macros
6
- # Specifies the relation between a single attachment and the model.
7
- #
8
- # class User < ActiveRecord::Base
9
- # has_one_attached :avatar
10
- # end
11
- #
12
- # There is no column defined on the model side, Active Storage takes
13
- # care of the mapping between your records and the attachment.
14
- #
15
- # To avoid N+1 queries, you can include the attached blobs in your query like so:
16
- #
17
- # User.with_attached_avatar
18
- #
19
- # Under the covers, this relationship is implemented as a +has_one+ association to a
20
- # ActiveStorage::Attachment record and a +has_one-through+ association to a
21
- # ActiveStorage::Blob record. These associations are available as +avatar_attachment+
22
- # and +avatar_blob+. But you shouldn't need to work with these associations directly in
23
- # most circumstances.
24
- #
25
- # The system has been designed to having you go through the ActiveStorage::Attached::One
26
- # proxy that provides the dynamic proxy to the associations and factory methods, like +attach+.
27
- #
28
- # If the +:dependent+ option isn't set, the attachment will be purged
29
- # (i.e. destroyed) whenever the record is destroyed.
30
- def has_one_attached(name, dependent: :purge_later)
31
- class_eval <<-CODE, __FILE__, __LINE__ + 1
32
- def #{name}
33
- @active_storage_attached_#{name} ||= ActiveStorage::Attached::One.new("#{name}", self, dependent: #{dependent == :purge_later ? ":purge_later" : "false"})
34
- end
35
-
36
- def #{name}=(attachable)
37
- #{name}.attach(attachable)
38
- end
39
- CODE
40
-
41
- has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record, dependent: false
42
- has_one :"#{name}_blob", through: :"#{name}_attachment", class_name: "ActiveStorage::Blob", source: :blob
43
-
44
- scope :"with_attached_#{name}", -> { includes("#{name}_attachment": :blob) }
45
-
46
- if dependent == :purge_later
47
- after_destroy_commit { public_send(name).purge_later }
48
- else
49
- before_destroy { public_send(name).detach }
50
- end
51
- end
52
-
53
- # Specifies the relation between multiple attachments and the model.
54
- #
55
- # class Gallery < ActiveRecord::Base
56
- # has_many_attached :photos
57
- # end
58
- #
59
- # There are no columns defined on the model side, Active Storage takes
60
- # care of the mapping between your records and the attachments.
61
- #
62
- # To avoid N+1 queries, you can include the attached blobs in your query like so:
63
- #
64
- # Gallery.where(user: Current.user).with_attached_photos
65
- #
66
- # Under the covers, this relationship is implemented as a +has_many+ association to a
67
- # ActiveStorage::Attachment record and a +has_many-through+ association to a
68
- # ActiveStorage::Blob record. These associations are available as +photos_attachments+
69
- # and +photos_blobs+. But you shouldn't need to work with these associations directly in
70
- # most circumstances.
71
- #
72
- # The system has been designed to having you go through the ActiveStorage::Attached::Many
73
- # proxy that provides the dynamic proxy to the associations and factory methods, like +#attach+.
74
- #
75
- # If the +:dependent+ option isn't set, all the attachments will be purged
76
- # (i.e. destroyed) whenever the record is destroyed.
77
- def has_many_attached(name, dependent: :purge_later)
78
- class_eval <<-CODE, __FILE__, __LINE__ + 1
79
- def #{name}
80
- @active_storage_attached_#{name} ||= ActiveStorage::Attached::Many.new("#{name}", self, dependent: #{dependent == :purge_later ? ":purge_later" : "false"})
81
- end
82
-
83
- def #{name}=(attachables)
84
- #{name}.attach(attachables)
85
- end
86
- CODE
87
-
88
- has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: false do
89
- def purge
90
- each(&:purge)
91
- reset
92
- end
93
-
94
- def purge_later
95
- each(&:purge_later)
96
- reset
97
- end
98
- end
99
- has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob
100
-
101
- scope :"with_attached_#{name}", -> { includes("#{name}_attachments": :blob) }
102
-
103
- if dependent == :purge_later
104
- after_destroy_commit { public_send(name).purge_later }
105
- else
106
- before_destroy { public_send(name).detach }
107
- end
108
- end
109
- end
110
- end