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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +145 -61
- data/MIT-LICENSE +1 -1
- data/README.md +9 -6
- data/app/assets/javascripts/activestorage.js +4 -1
- data/app/controllers/active_storage/base_controller.rb +3 -5
- data/app/controllers/active_storage/blobs_controller.rb +1 -1
- data/app/controllers/active_storage/disk_controller.rb +5 -2
- data/app/controllers/active_storage/representations_controller.rb +1 -1
- data/app/controllers/concerns/active_storage/set_current.rb +15 -0
- data/app/javascript/activestorage/blob_record.js +6 -1
- 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/purge_job.rb +3 -0
- data/app/models/active_storage/attachment.rb +20 -9
- data/app/models/active_storage/blob.rb +84 -31
- data/app/models/active_storage/blob/representable.rb +5 -5
- data/app/models/active_storage/filename.rb +0 -6
- data/app/models/active_storage/preview.rb +3 -3
- data/app/models/active_storage/variant.rb +51 -52
- data/app/models/active_storage/variation.rb +24 -33
- data/config/routes.rb +13 -12
- data/db/update_migrate/20180723000244_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.rb +9 -0
- data/lib/active_storage.rb +26 -6
- data/lib/active_storage/analyzer.rb +9 -4
- data/lib/active_storage/analyzer/image_analyzer.rb +11 -4
- data/lib/active_storage/analyzer/video_analyzer.rb +3 -5
- data/lib/active_storage/attached.rb +7 -22
- data/lib/active_storage/attached/changes.rb +16 -0
- data/lib/active_storage/attached/changes/create_many.rb +46 -0
- data/lib/active_storage/attached/changes/create_one.rb +69 -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/many.rb +16 -10
- data/lib/active_storage/attached/model.rb +147 -0
- data/lib/active_storage/attached/one.rb +16 -19
- data/lib/active_storage/downloader.rb +43 -0
- data/lib/active_storage/downloading.rb +8 -0
- data/lib/active_storage/engine.rb +43 -6
- data/lib/active_storage/errors.rb +22 -3
- data/lib/active_storage/gem_version.rb +4 -4
- data/lib/active_storage/previewer.rb +21 -11
- data/lib/active_storage/previewer/poppler_pdf_previewer.rb +2 -2
- data/lib/active_storage/previewer/video_previewer.rb +2 -3
- data/lib/active_storage/reflection.rb +64 -0
- data/lib/active_storage/service.rb +9 -6
- data/lib/active_storage/service/azure_storage_service.rb +30 -14
- data/lib/active_storage/service/configurator.rb +3 -1
- data/lib/active_storage/service/disk_service.rb +19 -11
- data/lib/active_storage/service/gcs_service.rb +49 -47
- data/lib/active_storage/service/s3_service.rb +10 -6
- data/lib/active_storage/transformers/image_processing_transformer.rb +39 -0
- data/lib/active_storage/transformers/mini_magick_transformer.rb +38 -0
- data/lib/active_storage/transformers/transformer.rb +42 -0
- data/lib/tasks/activestorage.rake +7 -0
- metadata +41 -12
- data/app/models/active_storage/filename/parameters.rb +0 -36
- 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
|
-
|
22
|
-
|
23
|
-
|
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:
|
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-
|
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:
|
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:
|
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:
|
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:
|
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/
|
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:
|
149
|
+
homepage: https://rubyonrails.org
|
124
150
|
licenses:
|
125
151
|
- MIT
|
126
152
|
metadata:
|
127
|
-
|
128
|
-
changelog_uri: https://github.com/rails/rails/blob/
|
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.
|
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
|