shrine 2.19.3 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +523 -41
  3. data/LICENSE.txt +1 -1
  4. data/README.md +83 -979
  5. data/doc/advantages.md +231 -204
  6. data/doc/attacher.md +304 -153
  7. data/doc/carrierwave.md +297 -226
  8. data/doc/changing_derivatives.md +308 -0
  9. data/doc/changing_location.md +103 -21
  10. data/doc/changing_storage.md +110 -0
  11. data/doc/creating_persistence_plugins.md +132 -0
  12. data/doc/creating_plugins.md +43 -23
  13. data/doc/creating_storages.md +19 -5
  14. data/doc/design.md +147 -97
  15. data/doc/direct_s3.md +38 -28
  16. data/doc/external/articles.md +63 -0
  17. data/doc/external/extensions.md +53 -0
  18. data/doc/external/misc.md +32 -0
  19. data/doc/getting_started.md +1156 -0
  20. data/doc/metadata.md +190 -109
  21. data/doc/multiple_files.md +93 -30
  22. data/doc/paperclip.md +384 -262
  23. data/doc/plugins/activerecord.md +177 -46
  24. data/doc/plugins/add_metadata.md +139 -38
  25. data/doc/plugins/atomic_helpers.md +217 -0
  26. data/doc/plugins/backgrounding.md +156 -98
  27. data/doc/plugins/cached_attachment_data.md +7 -5
  28. data/doc/plugins/column.md +121 -0
  29. data/doc/plugins/data_uri.md +23 -22
  30. data/doc/plugins/default_storage.md +36 -10
  31. data/doc/plugins/default_url.md +30 -13
  32. data/doc/plugins/delete_raw.md +4 -2
  33. data/doc/plugins/derivation_endpoint.md +186 -101
  34. data/doc/plugins/derivatives.md +839 -0
  35. data/doc/plugins/determine_mime_type.md +4 -2
  36. data/doc/plugins/download_endpoint.md +64 -8
  37. data/doc/plugins/dynamic_storage.md +5 -3
  38. data/doc/plugins/entity.md +263 -0
  39. data/doc/plugins/form_assign.md +55 -0
  40. data/doc/plugins/included.md +31 -8
  41. data/doc/plugins/infer_extension.md +21 -10
  42. data/doc/plugins/instrumentation.md +38 -16
  43. data/doc/plugins/keep_files.md +16 -17
  44. data/doc/plugins/metadata_attributes.md +42 -13
  45. data/doc/plugins/mirroring.md +118 -0
  46. data/doc/plugins/model.md +210 -0
  47. data/doc/plugins/module_include.md +4 -2
  48. data/doc/plugins/multi_cache.md +24 -0
  49. data/doc/plugins/persistence.md +101 -0
  50. data/doc/plugins/presign_endpoint.md +9 -4
  51. data/doc/plugins/pretty_location.md +16 -3
  52. data/doc/plugins/processing.md +4 -2
  53. data/doc/plugins/rack_file.md +8 -2
  54. data/doc/plugins/rack_response.md +6 -2
  55. data/doc/plugins/recache.md +4 -2
  56. data/doc/plugins/refresh_metadata.md +49 -9
  57. data/doc/plugins/remote_url.md +84 -47
  58. data/doc/plugins/remove_attachment.md +27 -6
  59. data/doc/plugins/remove_invalid.md +21 -6
  60. data/doc/plugins/restore_cached_data.md +11 -3
  61. data/doc/plugins/sequel.md +159 -35
  62. data/doc/plugins/signature.md +16 -5
  63. data/doc/plugins/store_dimensions.md +14 -2
  64. data/doc/plugins/tempfile.md +4 -2
  65. data/doc/plugins/type_predicates.md +96 -0
  66. data/doc/plugins/upload_endpoint.md +13 -13
  67. data/doc/plugins/upload_options.md +6 -4
  68. data/doc/plugins/{default_url_options.md → url_options.md} +9 -7
  69. data/doc/plugins/validation.md +97 -0
  70. data/doc/plugins/validation_helpers.md +16 -13
  71. data/doc/plugins/versions.md +15 -19
  72. data/doc/processing.md +438 -221
  73. data/doc/refile.md +188 -170
  74. data/doc/release_notes/1.0.0.md +4 -0
  75. data/doc/release_notes/1.1.0.md +6 -2
  76. data/doc/release_notes/1.2.0.md +4 -0
  77. data/doc/release_notes/1.3.0.md +4 -0
  78. data/doc/release_notes/1.4.0.md +4 -0
  79. data/doc/release_notes/1.4.1.md +4 -0
  80. data/doc/release_notes/1.4.2.md +4 -0
  81. data/doc/release_notes/2.0.0.md +4 -0
  82. data/doc/release_notes/2.0.1.md +4 -0
  83. data/doc/release_notes/2.1.0.md +5 -1
  84. data/doc/release_notes/2.1.1.md +4 -0
  85. data/doc/release_notes/2.10.0.md +4 -0
  86. data/doc/release_notes/2.10.1.md +4 -0
  87. data/doc/release_notes/2.11.0.md +4 -0
  88. data/doc/release_notes/2.12.0.md +4 -0
  89. data/doc/release_notes/2.13.0.md +4 -0
  90. data/doc/release_notes/2.14.0.md +5 -1
  91. data/doc/release_notes/2.15.0.md +11 -7
  92. data/doc/release_notes/2.16.0.md +4 -0
  93. data/doc/release_notes/2.17.0.md +4 -0
  94. data/doc/release_notes/2.18.0.md +4 -0
  95. data/doc/release_notes/2.19.0.md +6 -3
  96. data/doc/release_notes/2.2.0.md +4 -0
  97. data/doc/release_notes/2.3.0.md +4 -0
  98. data/doc/release_notes/2.3.1.md +4 -0
  99. data/doc/release_notes/2.4.0.md +4 -0
  100. data/doc/release_notes/2.4.1.md +4 -0
  101. data/doc/release_notes/2.5.0.md +4 -0
  102. data/doc/release_notes/2.6.0.md +4 -0
  103. data/doc/release_notes/2.6.1.md +4 -0
  104. data/doc/release_notes/2.7.0.md +4 -0
  105. data/doc/release_notes/2.8.0.md +4 -0
  106. data/doc/release_notes/2.9.0.md +4 -0
  107. data/doc/release_notes/3.0.0.md +981 -0
  108. data/doc/release_notes/3.0.1.md +22 -0
  109. data/doc/release_notes/3.1.0.md +73 -0
  110. data/doc/release_notes/3.2.0.md +96 -0
  111. data/doc/release_notes/3.2.1.md +31 -0
  112. data/doc/release_notes/3.2.2.md +14 -0
  113. data/doc/release_notes/3.3.0.md +105 -0
  114. data/doc/release_notes/3.4.0.md +35 -0
  115. data/doc/release_notes/3.5.0.md +63 -0
  116. data/doc/release_notes/3.6.0.md +23 -0
  117. data/doc/retrieving_uploads.md +5 -2
  118. data/doc/securing_uploads.md +60 -37
  119. data/doc/storage/file_system.md +20 -3
  120. data/doc/storage/memory.md +19 -0
  121. data/doc/storage/s3.md +122 -78
  122. data/doc/testing.md +141 -133
  123. data/doc/upgrading_to_3.md +708 -0
  124. data/doc/validation.md +54 -90
  125. data/lib/shrine/attacher.rb +292 -169
  126. data/lib/shrine/attachment.rb +13 -46
  127. data/lib/shrine/plugins/_persistence.rb +93 -0
  128. data/lib/shrine/plugins/activerecord.rb +77 -34
  129. data/lib/shrine/plugins/add_metadata.rb +25 -17
  130. data/lib/shrine/plugins/atomic_helpers.rb +119 -0
  131. data/lib/shrine/plugins/backgrounding.rb +77 -113
  132. data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
  133. data/lib/shrine/plugins/column.rb +102 -0
  134. data/lib/shrine/plugins/data_uri.rb +38 -36
  135. data/lib/shrine/plugins/default_storage.rb +45 -15
  136. data/lib/shrine/plugins/default_url.rb +12 -24
  137. data/lib/shrine/plugins/default_url_options.rb +3 -30
  138. data/lib/shrine/plugins/delete_raw.rb +10 -16
  139. data/lib/shrine/plugins/derivation_endpoint.rb +130 -171
  140. data/lib/shrine/plugins/derivatives.rb +645 -0
  141. data/lib/shrine/plugins/determine_mime_type.rb +9 -21
  142. data/lib/shrine/plugins/download_endpoint.rb +118 -133
  143. data/lib/shrine/plugins/dynamic_storage.rb +5 -11
  144. data/lib/shrine/plugins/entity.rb +158 -0
  145. data/lib/shrine/plugins/form_assign.rb +108 -0
  146. data/lib/shrine/plugins/included.rb +6 -6
  147. data/lib/shrine/plugins/infer_extension.rb +17 -20
  148. data/lib/shrine/plugins/instrumentation.rb +59 -43
  149. data/lib/shrine/plugins/keep_files.rb +3 -15
  150. data/lib/shrine/plugins/metadata_attributes.rb +28 -19
  151. data/lib/shrine/plugins/mirroring.rb +142 -0
  152. data/lib/shrine/plugins/model.rb +160 -0
  153. data/lib/shrine/plugins/module_include.rb +3 -3
  154. data/lib/shrine/plugins/multi_cache.rb +27 -0
  155. data/lib/shrine/plugins/presign_endpoint.rb +27 -28
  156. data/lib/shrine/plugins/pretty_location.rb +15 -9
  157. data/lib/shrine/plugins/processing.rb +22 -9
  158. data/lib/shrine/plugins/rack_file.rb +2 -42
  159. data/lib/shrine/plugins/rack_response.rb +21 -10
  160. data/lib/shrine/plugins/recache.rb +6 -5
  161. data/lib/shrine/plugins/refresh_metadata.rb +13 -11
  162. data/lib/shrine/plugins/remote_url.rb +49 -49
  163. data/lib/shrine/plugins/remove_attachment.rb +12 -6
  164. data/lib/shrine/plugins/remove_invalid.rb +19 -8
  165. data/lib/shrine/plugins/restore_cached_data.rb +13 -7
  166. data/lib/shrine/plugins/sequel.rb +86 -36
  167. data/lib/shrine/plugins/signature.rb +10 -16
  168. data/lib/shrine/plugins/store_dimensions.rb +35 -40
  169. data/lib/shrine/plugins/tempfile.rb +1 -3
  170. data/lib/shrine/plugins/type_predicates.rb +113 -0
  171. data/lib/shrine/plugins/upload_endpoint.rb +28 -24
  172. data/lib/shrine/plugins/upload_options.rb +14 -15
  173. data/lib/shrine/plugins/url_options.rb +31 -0
  174. data/lib/shrine/plugins/validation.rb +80 -0
  175. data/lib/shrine/plugins/validation_helpers.rb +35 -58
  176. data/lib/shrine/plugins/versions.rb +107 -87
  177. data/lib/shrine/plugins.rb +22 -0
  178. data/lib/shrine/storage/file_system.rb +46 -64
  179. data/lib/shrine/storage/linter.rb +42 -7
  180. data/lib/shrine/storage/memory.rb +49 -0
  181. data/lib/shrine/storage/s3.rb +173 -160
  182. data/lib/shrine/uploaded_file.rb +32 -32
  183. data/lib/shrine/version.rb +3 -3
  184. data/lib/shrine.rb +87 -150
  185. data/shrine.gemspec +11 -12
  186. metadata +92 -82
  187. data/doc/migrating_storage.md +0 -76
  188. data/doc/plugins/backup.md +0 -31
  189. data/doc/plugins/copy.md +0 -24
  190. data/doc/plugins/delete_promoted.md +0 -12
  191. data/doc/plugins/direct_upload.md +0 -172
  192. data/doc/plugins/hooks.md +0 -58
  193. data/doc/plugins/logging.md +0 -42
  194. data/doc/plugins/migration_helpers.md +0 -60
  195. data/doc/plugins/moving.md +0 -19
  196. data/doc/plugins/multi_delete.md +0 -20
  197. data/doc/plugins/parallelize.md +0 -16
  198. data/doc/plugins/parsed_json.md +0 -23
  199. data/doc/regenerating_versions.md +0 -143
  200. data/lib/shrine/plugins/background_helpers.rb +0 -5
  201. data/lib/shrine/plugins/backup.rb +0 -90
  202. data/lib/shrine/plugins/copy.rb +0 -50
  203. data/lib/shrine/plugins/delete_promoted.rb +0 -20
  204. data/lib/shrine/plugins/direct_upload.rb +0 -217
  205. data/lib/shrine/plugins/hooks.rb +0 -90
  206. data/lib/shrine/plugins/logging.rb +0 -142
  207. data/lib/shrine/plugins/migration_helpers.rb +0 -70
  208. data/lib/shrine/plugins/moving.rb +0 -57
  209. data/lib/shrine/plugins/multi_delete.rb +0 -32
  210. data/lib/shrine/plugins/parallelize.rb +0 -78
  211. data/lib/shrine/plugins/parsed_json.rb +0 -29
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The copy plugin is deprecated and will be removed in Shrine 3.")
4
-
5
- class Shrine
6
- module Plugins
7
- # Documentation lives in [doc/plugins/copy.md] on GitHub.
8
- #
9
- # [doc/plugins/copy.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/copy.md
10
- module Copy
11
- module AttachmentMethods
12
- def initialize(*)
13
- super
14
-
15
- name = attachment_name
16
-
17
- define_method :initialize_copy do |record|
18
- super(record)
19
- instance_variable_set(:"@#{name}_attacher", nil) # reload the attacher
20
- attacher = send(:"#{name}_attacher")
21
- attacher.send(:write, nil) # remove original attachment
22
- attacher.copy(record.public_send(:"#{name}_attacher"))
23
- end
24
-
25
- # Fix for JRuby
26
- private :initialize_copy
27
- end
28
- end
29
-
30
- module AttacherMethods
31
- def copy(attacher)
32
- options = {action: :copy, move: false}
33
-
34
- copied_attachment = if attacher.cached?
35
- cache!(attacher.get, **options)
36
- elsif attacher.stored?
37
- store!(attacher.get, **options)
38
- else
39
- nil
40
- end
41
-
42
- @old = get
43
- _set(copied_attachment)
44
- end
45
- end
46
- end
47
-
48
- register_plugin(:copy, Copy)
49
- end
50
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Shrine
4
- module Plugins
5
- # Documentation lives in [doc/plugins/delete_promoted.md] on GitHub.
6
- #
7
- # [doc/plugins/delete_promoted.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/delete_promoted.md
8
- module DeletePromoted
9
- module AttacherMethods
10
- def promote(uploaded_file = get, **options)
11
- result = super
12
- _delete(uploaded_file, action: :promote)
13
- result
14
- end
15
- end
16
- end
17
-
18
- register_plugin(:delete_promoted, DeletePromoted)
19
- end
20
- end
@@ -1,217 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The direct_upload plugin has been deprecated in favor of upload_endpoint and presign_endpoint plugins. The direct_upload plugin will be removed in Shrine 3.")
4
-
5
- require "roda"
6
- require "json"
7
-
8
- class Shrine
9
- module Plugins
10
- # Documentation lives in [doc/plugins/direct_upload.md] on GitHub.
11
- #
12
- # [doc/plugins/direct_upload.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/direct_upload.md
13
- module DirectUpload
14
- def self.load_dependencies(uploader, *)
15
- uploader.plugin :rack_file
16
- end
17
-
18
- def self.configure(uploader, opts = {})
19
- uploader.opts[:direct_upload_allowed_storages] = opts.fetch(:allowed_storages, uploader.opts.fetch(:direct_upload_allowed_storages, [:cache]))
20
- uploader.opts[:direct_upload_presign_options] = opts.fetch(:presign_options, uploader.opts.fetch(:direct_upload_presign_options, {}))
21
- uploader.opts[:direct_upload_presign_location] = opts.fetch(:presign_location, uploader.opts[:direct_upload_presign_location])
22
- uploader.opts[:direct_upload_max_size] = opts.fetch(:max_size, uploader.opts[:direct_upload_max_size])
23
-
24
- uploader.assign_upload_endpoint(App) unless uploader.const_defined?(:UploadEndpoint)
25
- end
26
-
27
- module ClassMethods
28
- # Assigns the subclass a copy of the upload endpoint class.
29
- def inherited(subclass)
30
- super
31
- subclass.assign_upload_endpoint(self::UploadEndpoint)
32
- end
33
-
34
- # Assigns the subclassed endpoint as the `UploadEndpoint` constant.
35
- def assign_upload_endpoint(klass)
36
- endpoint_class = Class.new(klass)
37
- endpoint_class.opts[:shrine_class] = self
38
- const_set(:UploadEndpoint, endpoint_class)
39
- end
40
- end
41
-
42
- # Routes incoming requests. It first asserts that the storage is existent
43
- # and allowed, then the filesize isn't too large. Afterwards it proceeds
44
- # with the file upload and returns the uploaded file as JSON.
45
- class App < Roda
46
- plugin :default_headers, "Content-Type"=>"application/json"
47
- plugin :placeholder_string_matchers if Gem::Version.new(Roda::RodaVersion) >= Gem::Version.new("3.0.0")
48
-
49
- route do |r|
50
- r.on ":storage" do |storage_key|
51
- @uploader = get_uploader(storage_key)
52
-
53
- r.post ["upload", ":name"] do |name|
54
- file = get_file
55
- context = get_context(name)
56
-
57
- uploaded_file = upload(file, context)
58
-
59
- json uploaded_file
60
- end
61
-
62
- r.get "presign" do
63
- location = get_presign_location
64
- options = get_presign_options
65
-
66
- presign_data = generate_presign(location, options)
67
- response.headers["Cache-Control"] = "no-store"
68
-
69
- json presign_data
70
- end
71
- end
72
- end
73
-
74
- private
75
-
76
- attr_reader :uploader
77
-
78
- # Instantiates the uploader, checking first if the storage is allowed.
79
- def get_uploader(storage_key)
80
- allow_storage!(storage_key)
81
- shrine_class.new(storage_key.to_sym)
82
- end
83
-
84
- # Retrieves the context for the upload.
85
- def get_context(name)
86
- context = {action: :cache, phase: :cache}
87
-
88
- if name != "upload"
89
- Shrine.deprecation("The \"POST /:storage/:name\" route of the direct_upload plugin is deprecated, and it will be removed in Shrine 3. Use \"POST /:storage/upload\" instead.")
90
- context[:name] = name
91
- end
92
-
93
- unless presign_storage?
94
- context[:location] = request.params["key"]
95
- end
96
-
97
- context
98
- end
99
-
100
- # Uploads the file to the requested storage.
101
- def upload(file, context)
102
- uploader.upload(file, context)
103
- end
104
-
105
- # Generates a unique location, or calls `:presign_location`.
106
- def get_presign_location
107
- if presign_location
108
- presign_location.call(request)
109
- else
110
- extension = request.params["extension"]
111
- extension.prepend(".") if extension && !extension.start_with?(".")
112
- uploader.send(:generate_uid, nil) + extension.to_s
113
- end
114
- end
115
-
116
- # Returns dynamic options for generating the presign.
117
- def get_presign_options
118
- options = presign_options
119
- options = options.call(request) if options.respond_to?(:call)
120
- options || {}
121
- end
122
-
123
- # Generates the presign hash for the request.
124
- def generate_presign(location, options)
125
- if presign_storage?
126
- generate_real_presign(location, options)
127
- else
128
- generate_fake_presign(location, options)
129
- end
130
- end
131
-
132
- # Generates a presign by calling the storage.
133
- def generate_real_presign(location, options)
134
- signature = uploader.storage.presign(location, options)
135
- {url: signature.url, fields: signature.fields}
136
- end
137
-
138
- # Generates a presign that points to the direct upload endpoint.
139
- def generate_fake_presign(location, options)
140
- url = request.url.sub(/presign[^\/]*$/, "upload")
141
- {url: url, fields: {key: location}}
142
- end
143
-
144
- # Returns true if the storage supports presigns.
145
- def presign_storage?
146
- uploader.storage.respond_to?(:presign)
147
- end
148
-
149
- # Halts the request if storage is not allowed.
150
- def allow_storage!(storage_key)
151
- if !allowed_storages.map(&:to_s).include?(storage_key)
152
- error! 403, "Storage #{storage_key.inspect} is not allowed."
153
- end
154
- end
155
-
156
- # Returns the Rack file wrapped in an IO-like object. If "file" is
157
- # missing or is too big, the request is halted.
158
- def get_file
159
- file = require_param!("file")
160
- error! 400, "The \"file\" query parameter is not a file." if !(file.is_a?(Hash) && file.key?(:tempfile))
161
- check_filesize!(file[:tempfile]) if max_size
162
-
163
- RackFile::UploadedFile.new(file)
164
- end
165
-
166
- # If the file is too big, deletes the file and halts the request.
167
- def check_filesize!(file)
168
- if file.size > max_size
169
- file.delete
170
- megabytes = max_size.to_f / 1024 / 1024
171
- error! 413, "The file is too big (maximum size is #{megabytes} MB)."
172
- end
173
- end
174
-
175
- # Loudly requires the param.
176
- def require_param!(name)
177
- request.params.fetch(name)
178
- rescue KeyError
179
- error! 400, "Missing query parameter: #{name.inspect}"
180
- end
181
-
182
- # Halts the request with the error message.
183
- def error!(status, message)
184
- response.status = status
185
- response.write({error: message}.to_json)
186
- request.halt
187
- end
188
-
189
- def json(object)
190
- object.to_json
191
- end
192
-
193
- def shrine_class
194
- opts[:shrine_class]
195
- end
196
-
197
- def allowed_storages
198
- shrine_class.opts[:direct_upload_allowed_storages]
199
- end
200
-
201
- def presign_options
202
- shrine_class.opts[:direct_upload_presign_options]
203
- end
204
-
205
- def presign_location
206
- shrine_class.opts[:direct_upload_presign_location]
207
- end
208
-
209
- def max_size
210
- shrine_class.opts[:direct_upload_max_size]
211
- end
212
- end
213
- end
214
-
215
- register_plugin(:direct_upload, DirectUpload)
216
- end
217
- end
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Shrine
4
- module Plugins
5
- # Documentation lives in [doc/plugins/hooks.md] on GitHub.
6
- #
7
- # [doc/plugins/hooks.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/hooks.md
8
- module Hooks
9
- module InstanceMethods
10
- def upload(io, context = {})
11
- result = nil
12
- before_upload(io, context)
13
- around_upload(io, context) { result = super }
14
- after_upload(io, context)
15
- result
16
- end
17
-
18
- def around_upload(*args)
19
- yield
20
- end
21
-
22
- def before_upload(*)
23
- end
24
-
25
- def after_upload(*)
26
- end
27
-
28
-
29
- def processed(io, context)
30
- result = nil
31
- before_process(io, context)
32
- around_process(io, context) { result = super }
33
- after_process(io, context)
34
- result
35
- end
36
- private :processed
37
-
38
- def around_process(*args)
39
- yield
40
- end
41
-
42
- def before_process(*)
43
- end
44
-
45
- def after_process(*)
46
- end
47
-
48
-
49
- def store(io, context = {})
50
- result = nil
51
- before_store(io, context)
52
- around_store(io, context) { result = super }
53
- after_store(io, context)
54
- result
55
- end
56
-
57
- def around_store(*args)
58
- yield
59
- end
60
-
61
- def before_store(*)
62
- end
63
-
64
- def after_store(*)
65
- end
66
-
67
-
68
- def delete(io, context = {})
69
- result = nil
70
- before_delete(io, context)
71
- around_delete(io, context) { result = super }
72
- after_delete(io, context)
73
- result
74
- end
75
-
76
- def around_delete(*args)
77
- yield
78
- end
79
-
80
- def before_delete(*)
81
- end
82
-
83
- def after_delete(*)
84
- end
85
- end
86
- end
87
-
88
- register_plugin(:hooks, Hooks)
89
- end
90
- end
@@ -1,142 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The logging plugin has been deprecated in favor of instrumentation plugin. The logging plugin will be removed in Shrine 3.")
4
-
5
- require "logger"
6
- require "json"
7
- require "time"
8
-
9
- class Shrine
10
- module Plugins
11
- # Documentation lives in [doc/plugins/logging.md] on GitHub.
12
- #
13
- # [doc/plugins/logging.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/logging.md
14
- module Logging
15
- def self.load_dependencies(uploader, *)
16
- uploader.plugin :hooks
17
- end
18
-
19
- def self.configure(uploader, opts = {})
20
- uploader.opts[:logging_stream] = opts.fetch(:stream, uploader.opts.fetch(:logging_stream, $stdout))
21
- uploader.opts[:logging_logger] = opts.fetch(:logger, uploader.opts.fetch(:logging_logger, uploader.create_logger))
22
- uploader.opts[:logging_format] = opts.fetch(:format, uploader.opts.fetch(:logging_format, :human))
23
-
24
- Shrine.deprecation("The :heroku logging format has been renamed to :logfmt. Using :heroku name will stop being supported in Shrine 3.") if uploader.opts[:logging_format] == :heroku
25
- end
26
-
27
- module ClassMethods
28
- def logger=(logger)
29
- @logger = logger
30
- end
31
-
32
- def logger
33
- @logger ||= opts[:logging_logger]
34
- end
35
-
36
- def create_logger
37
- logger = Logger.new(opts[:logging_stream])
38
- logger.level = Logger::INFO
39
- logger.level = Logger::WARN if ENV["RACK_ENV"] == "test"
40
- logger.formatter = pretty_formatter
41
- logger
42
- end
43
-
44
- # It makes logging preamble simpler than the default logger. Also, it
45
- # doesn't output timestamps if on Heroku.
46
- def pretty_formatter
47
- proc do |severity, time, program_name, message|
48
- output = "#{Process.pid}: #{message}\n".dup
49
- output.prepend "#{time.utc.iso8601(3)} " unless ENV["DYNO"]
50
- output
51
- end
52
- end
53
- end
54
-
55
- module InstanceMethods
56
- def store(io, context = {})
57
- log("store", io, context) { super }
58
- end
59
-
60
- def delete(io, context = {})
61
- log("delete", io, context) { super }
62
- end
63
-
64
- private
65
-
66
- def processed(io, context = {})
67
- log("process", io, context) { super }
68
- end
69
-
70
- # Collects the data and sends it for logging.
71
- def log(action, input, context)
72
- result, duration = benchmark { yield }
73
-
74
- _log(
75
- action: action,
76
- phase: context[:action],
77
- uploader: self.class.to_s,
78
- attachment: context[:name],
79
- record_class: (context[:record].class.to_s if context[:record]),
80
- record_id: (context[:record].id if context[:record].respond_to?(:id)),
81
- files: (action == "process" ? [count(input), count(result)] : count(result)),
82
- duration: ("%.2f" % duration).to_f,
83
- ) unless result.nil?
84
-
85
- result
86
- end
87
-
88
- # Determines format of logging and calls appropriate method.
89
- def _log(data)
90
- message = send("_log_message_#{opts[:logging_format]}", data)
91
- self.class.logger.info(message)
92
- end
93
-
94
- def _log_message_human(data)
95
- components = []
96
- components << "#{data[:action].upcase}"
97
- components[-1] += "[#{data[:phase]}]" if data[:phase]
98
- components << "#{data[:uploader]}"
99
- components[-1] += "[:#{data[:attachment]}]" if data[:attachment]
100
- components << "#{data[:record_class]}" if data[:record_class]
101
- components[-1] += "[#{data[:record_id]}]" if data[:record_id]
102
- components << "#{Array(data[:files]).join("-")} #{"file#{"s" if Array(data[:files]).any?{|n| n > 1}}"}"
103
- components << "(#{data[:duration]}s)"
104
- components.join(" ")
105
- end
106
-
107
- def _log_message_json(data)
108
- data[:files] = Array(data[:files]).join("-")
109
- JSON.generate(data)
110
- end
111
-
112
- def _log_message_logfmt(data)
113
- data[:files] = Array(data[:files]).join("-")
114
- data.map { |key, value| "#{key}=#{value}" }.join(" ")
115
- end
116
- alias _log_message_heroku _log_message_logfmt # deprecated alias
117
-
118
- # We may have one file, a hash of versions, or an array of files or
119
- # hashes.
120
- def count(object)
121
- case object
122
- when Hash
123
- object.count
124
- when Array
125
- object.inject(0) { |sum, o| sum += count(o) }
126
- else
127
- 1
128
- end
129
- end
130
-
131
- def benchmark
132
- start = Time.now
133
- result = yield
134
- finish = Time.now
135
- [result, finish - start]
136
- end
137
- end
138
- end
139
-
140
- register_plugin(:logging, Logging)
141
- end
142
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The migration_helpers plugin is deprecated and will be removed in Shrine 3. Attacher#cached? and Attacher#stored? have been moved to base.")
4
-
5
- class Shrine
6
- module Plugins
7
- # Documentation lives in [doc/plugins/migration_helpers.md] on GitHub.
8
- #
9
- # [doc/plugins/migration_helpers.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/migration_helpers.md
10
- module MigrationHelpers
11
- def self.configure(uploader, delegate: false)
12
- uploader.opts[:migration_helpers_delegate] = delegate
13
- end
14
-
15
- module AttachmentMethods
16
- def initialize(name)
17
- super
18
-
19
- return if shrine_class.opts[:migration_helpers_delegate] == false
20
-
21
- name = attachment_name
22
-
23
- define_method :"update_#{name}" do |&block|
24
- send(:"#{name}_attacher").update_stored(&block)
25
- end
26
-
27
- define_method :"#{name}_cache" do
28
- send(:"#{name}_attacher").cache
29
- end
30
-
31
- define_method :"#{name}_store" do
32
- send(:"#{name}_attacher").store
33
- end
34
-
35
- define_method :"#{name}_cached?" do
36
- send(:"#{name}_attacher").cached?
37
- end
38
-
39
- define_method :"#{name}_stored?" do
40
- send(:"#{name}_attacher").stored?
41
- end
42
- end
43
- end
44
-
45
- module AttacherMethods
46
- # Updates the attachment with the result of the block. It will get
47
- # called only if the attachment exists and is stored.
48
- def update_stored(&block)
49
- return if get.nil? || cache.uploaded?(get)
50
- new_attachment = block.call(get)
51
- swap(new_attachment)
52
- end
53
-
54
- # Returns true if the attachment is present and is uploaded by the
55
- # temporary storage.
56
- def cached?
57
- get && cache.uploaded?(get)
58
- end
59
-
60
- # Returns true if the attachment is present and is uploaded by the
61
- # permanent storage.
62
- def stored?
63
- get && store.uploaded?(get)
64
- end
65
- end
66
- end
67
-
68
- register_plugin(:migration_helpers, MigrationHelpers)
69
- end
70
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The moving plugin has been deprecated in favor of the :move upload option for FileSystem storage. It will no longer be available in Shrine 3.")
4
-
5
- class Shrine
6
- module Plugins
7
- # Documentation lives in [doc/plugins/moving.md] on GitHub.
8
- #
9
- # [doc/plugins/moving.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/moving.md
10
- module Moving
11
- def self.configure(uploader, opts = {})
12
- uploader.opts[:moving_storages] = opts.fetch(:storages, uploader.opts[:moving_storages])
13
- end
14
-
15
- module InstanceMethods
16
- private
17
-
18
- # Moves the file if storage supports it, otherwise defaults to copying.
19
- def copy(io, context)
20
- if move?(io, context)
21
- move(io, context)
22
- else
23
- super
24
- end
25
- end
26
-
27
- # Generates upload options and calls `#move` on the storage.
28
- def move(io, context)
29
- location = context[:location]
30
- metadata = context[:metadata]
31
- upload_options = context[:upload_options] || {}
32
-
33
- storage.move(io, location, shrine_metadata: metadata, **upload_options)
34
- end
35
-
36
- # Returns true if file should be moved and is movable.
37
- def move?(io, context)
38
- return false if context[:move] == false
39
- moving_storage? && movable?(io, context)
40
- end
41
-
42
- # Returns true if storage can move this file.
43
- def movable?(io, context)
44
- storage.respond_to?(:move) && storage.movable?(io, context[:location])
45
- end
46
-
47
- # Returns true if file should be moved.
48
- def moving_storage?
49
- opts[:moving_storages].nil? ||
50
- opts[:moving_storages].include?(storage_key)
51
- end
52
- end
53
- end
54
-
55
- register_plugin(:moving, Moving)
56
- end
57
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The multi_delete plugin is deprecated and will be removed in Shrine 3.")
4
-
5
- class Shrine
6
- module Plugins
7
- # Documentation lives in [doc/plugins/multi_delete.md] on GitHub.
8
- #
9
- # [doc/plugins/multi_delete.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/multi_delete.md
10
- module MultiDelete
11
- module InstanceMethods
12
- private
13
-
14
- # Adds the ability to upload multiple files, leveraging the underlying
15
- # storage's potential multi delete capability.
16
- def _delete(uploaded_file, context)
17
- if uploaded_file.is_a?(Array)
18
- if storage.respond_to?(:multi_delete)
19
- storage.multi_delete(uploaded_file.map(&:id))
20
- else
21
- uploaded_file.each { |file| _delete(file, context) }
22
- end
23
- else
24
- super
25
- end
26
- end
27
- end
28
- end
29
-
30
- register_plugin(:multi_delete, MultiDelete)
31
- end
32
- end