shrine 2.19.4 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +485 -43
  3. data/LICENSE.txt +1 -1
  4. data/README.md +81 -977
  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 +102 -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 +1115 -0
  20. data/doc/metadata.md +190 -109
  21. data/doc/multiple_files.md +62 -34
  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 +162 -101
  34. data/doc/plugins/derivatives.md +829 -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 +14 -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 +185 -167
  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 +4 -0
  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/retrieving_uploads.md +4 -1
  116. data/doc/securing_uploads.md +60 -37
  117. data/doc/storage/file_system.md +20 -3
  118. data/doc/storage/memory.md +19 -0
  119. data/doc/storage/s3.md +117 -83
  120. data/doc/testing.md +124 -144
  121. data/doc/upgrading_to_3.md +710 -0
  122. data/doc/validation.md +54 -90
  123. data/lib/shrine/attacher.rb +287 -171
  124. data/lib/shrine/attachment.rb +13 -46
  125. data/lib/shrine/plugins/_persistence.rb +93 -0
  126. data/lib/shrine/plugins/activerecord.rb +77 -34
  127. data/lib/shrine/plugins/add_metadata.rb +25 -17
  128. data/lib/shrine/plugins/atomic_helpers.rb +119 -0
  129. data/lib/shrine/plugins/backgrounding.rb +77 -113
  130. data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
  131. data/lib/shrine/plugins/column.rb +102 -0
  132. data/lib/shrine/plugins/data_uri.rb +38 -36
  133. data/lib/shrine/plugins/default_storage.rb +45 -15
  134. data/lib/shrine/plugins/default_url.rb +12 -24
  135. data/lib/shrine/plugins/default_url_options.rb +3 -30
  136. data/lib/shrine/plugins/delete_raw.rb +10 -16
  137. data/lib/shrine/plugins/derivation_endpoint.rb +89 -134
  138. data/lib/shrine/plugins/derivatives.rb +637 -0
  139. data/lib/shrine/plugins/determine_mime_type.rb +9 -21
  140. data/lib/shrine/plugins/download_endpoint.rb +109 -133
  141. data/lib/shrine/plugins/dynamic_storage.rb +5 -11
  142. data/lib/shrine/plugins/entity.rb +152 -0
  143. data/lib/shrine/plugins/form_assign.rb +108 -0
  144. data/lib/shrine/plugins/included.rb +6 -6
  145. data/lib/shrine/plugins/infer_extension.rb +13 -20
  146. data/lib/shrine/plugins/instrumentation.rb +54 -42
  147. data/lib/shrine/plugins/keep_files.rb +3 -15
  148. data/lib/shrine/plugins/metadata_attributes.rb +28 -19
  149. data/lib/shrine/plugins/mirroring.rb +142 -0
  150. data/lib/shrine/plugins/model.rb +158 -0
  151. data/lib/shrine/plugins/module_include.rb +3 -3
  152. data/lib/shrine/plugins/multi_cache.rb +27 -0
  153. data/lib/shrine/plugins/presign_endpoint.rb +18 -22
  154. data/lib/shrine/plugins/pretty_location.rb +15 -9
  155. data/lib/shrine/plugins/processing.rb +22 -9
  156. data/lib/shrine/plugins/rack_file.rb +2 -42
  157. data/lib/shrine/plugins/rack_response.rb +15 -10
  158. data/lib/shrine/plugins/recache.rb +6 -5
  159. data/lib/shrine/plugins/refresh_metadata.rb +13 -11
  160. data/lib/shrine/plugins/remote_url.rb +49 -49
  161. data/lib/shrine/plugins/remove_attachment.rb +10 -6
  162. data/lib/shrine/plugins/remove_invalid.rb +19 -8
  163. data/lib/shrine/plugins/restore_cached_data.rb +13 -7
  164. data/lib/shrine/plugins/sequel.rb +86 -36
  165. data/lib/shrine/plugins/signature.rb +10 -16
  166. data/lib/shrine/plugins/store_dimensions.rb +35 -40
  167. data/lib/shrine/plugins/tempfile.rb +1 -3
  168. data/lib/shrine/plugins/type_predicates.rb +113 -0
  169. data/lib/shrine/plugins/upload_endpoint.rb +25 -23
  170. data/lib/shrine/plugins/upload_options.rb +14 -15
  171. data/lib/shrine/plugins/url_options.rb +31 -0
  172. data/lib/shrine/plugins/validation.rb +80 -0
  173. data/lib/shrine/plugins/validation_helpers.rb +34 -57
  174. data/lib/shrine/plugins/versions.rb +107 -87
  175. data/lib/shrine/plugins.rb +22 -0
  176. data/lib/shrine/storage/file_system.rb +46 -64
  177. data/lib/shrine/storage/linter.rb +42 -7
  178. data/lib/shrine/storage/memory.rb +49 -0
  179. data/lib/shrine/storage/s3.rb +154 -158
  180. data/lib/shrine/uploaded_file.rb +28 -30
  181. data/lib/shrine/version.rb +3 -3
  182. data/lib/shrine.rb +86 -149
  183. data/shrine.gemspec +9 -10
  184. metadata +79 -83
  185. data/doc/migrating_storage.md +0 -76
  186. data/doc/plugins/backup.md +0 -31
  187. data/doc/plugins/copy.md +0 -24
  188. data/doc/plugins/delete_promoted.md +0 -12
  189. data/doc/plugins/direct_upload.md +0 -172
  190. data/doc/plugins/hooks.md +0 -58
  191. data/doc/plugins/logging.md +0 -42
  192. data/doc/plugins/migration_helpers.md +0 -60
  193. data/doc/plugins/moving.md +0 -19
  194. data/doc/plugins/multi_delete.md +0 -20
  195. data/doc/plugins/parallelize.md +0 -16
  196. data/doc/plugins/parsed_json.md +0 -23
  197. data/doc/regenerating_versions.md +0 -143
  198. data/lib/shrine/plugins/background_helpers.rb +0 -5
  199. data/lib/shrine/plugins/backup.rb +0 -90
  200. data/lib/shrine/plugins/copy.rb +0 -50
  201. data/lib/shrine/plugins/delete_promoted.rb +0 -20
  202. data/lib/shrine/plugins/direct_upload.rb +0 -217
  203. data/lib/shrine/plugins/hooks.rb +0 -90
  204. data/lib/shrine/plugins/logging.rb +0 -142
  205. data/lib/shrine/plugins/migration_helpers.rb +0 -70
  206. data/lib/shrine/plugins/moving.rb +0 -57
  207. data/lib/shrine/plugins/multi_delete.rb +0 -32
  208. data/lib/shrine/plugins/parallelize.rb +0 -78
  209. data/lib/shrine/plugins/parsed_json.rb +0 -29
data/doc/testing.md CHANGED
@@ -1,4 +1,6 @@
1
- # Testing with Shrine
1
+ ---
2
+ title: Testing with Shrine
3
+ ---
2
4
 
3
5
  The goal of this guide is to provide some useful tips for testing file
4
6
  attachments implemented with Shrine in your application.
@@ -6,9 +8,9 @@ attachments implemented with Shrine in your application.
6
8
  ## Callbacks
7
9
 
8
10
  When you first try to test file attachments, you might experience that files
9
- are simply not being promoted (uploaded from temporary to permanent storage).
10
- This is because your tests are likely setup to be wrapped inside database
11
- transactions, and that doesn't work with Shrine callbacks.
11
+ are not being promoted to permanent storage. This is because your tests are
12
+ likely setup to be wrapped inside database transactions, and that doesn't work
13
+ with Shrine callbacks.
12
14
 
13
15
  Specifically, Shrine uses "after commit" callbacks for promoting and deleting
14
16
  attached files. This means that if your tests are wrapped inside transactions,
@@ -18,7 +20,7 @@ happens only after the test has already finished.
18
20
  ```rb
19
21
  # Promoting will happen only after the test transaction commits
20
22
  it "can attach images" do
21
- photo = Photo.create(image: image_file)
23
+ photo = Photo.create(image: file)
22
24
  photo.image.storage_key #=> :cache (we expected it to be promoted to permanent storage)
23
25
  end
24
26
  ```
@@ -37,15 +39,10 @@ end
37
39
  ## Storage
38
40
 
39
41
  If you're using FileSystem storage and your tests run in a single process,
40
- you can switch to [memory storage][shrine-memory], which is both faster and
41
- doesn't require you to clean up anything between tests.
42
+ you can switch to `Shrine::Storage::Memory`, which is both faster and doesn't
43
+ require you to clean up anything between tests.
42
44
 
43
45
  ```rb
44
- # Gemfile
45
- gem "shrine-memory"
46
- ```
47
- ```rb
48
- # test/test_helper.rb
49
46
  require "shrine/storage/memory"
50
47
 
51
48
  Shrine.storages = {
@@ -100,189 +97,172 @@ subdomains when generating URLs.
100
97
 
101
98
  ## Test data
102
99
 
103
- If you're creating test data dynamically using libraries like [factory_bot],
104
- you can have the test file assigned dynamically when the record is created:
100
+ We want to keep our tests fast, so when we're setting up files for tests, we
101
+ want to avoid expensive operations such as file processing and metadata
102
+ extraction.
103
+
104
+ We can create a helper method that will create attached file data for us, and
105
+ use that with our factories/fixtures.
105
106
 
106
107
  ```rb
107
- factory :photo do
108
- image { File.open("test/files/image.jpg") }
109
- end
110
- ```
108
+ module TestData
109
+ module_function
111
110
 
112
- On the other hand, if you're setting up test data using Rails' YAML fixtures,
113
- you unfortunately won't be able to use them for assigning files. This is
114
- because Rails fixtures only allow assigning primitive data types, and don't
115
- allow you to specify Shrine attributes - you can only assign to columns
116
- directly.
111
+ def image_data
112
+ attacher = Shrine::Attacher.new
113
+ attacher.set(uploaded_image)
117
114
 
118
- ## Background jobs
115
+ # if you're processing derivatives
116
+ attacher.set_derivatives(
117
+ large: uploaded_image,
118
+ medium: uploaded_image,
119
+ small: uploaded_image,
120
+ )
119
121
 
120
- If you're using background jobs with Shrine, you probably want to make them
121
- synchronous in tests. Your favourite backgrounding library should already
122
- support this, examples:
122
+ attacher.column_data # or attacher.data in case of postgres jsonb column
123
+ end
123
124
 
124
- ```rb
125
- # Sidekiq
126
- require "sidekiq/testing"
127
- Sidekiq::Testing.inline!
128
- ```
125
+ def uploaded_image
126
+ file = File.open("test/files/image.jpg", binmode: true)
127
+
128
+ # for performance we skip metadata extraction and assign test metadata
129
+ uploaded_file = Shrine.upload(file, :store, metadata: false)
130
+ uploaded_file.metadata.merge!(
131
+ "size" => File.size(file.path),
132
+ "mime_type" => "image/jpeg",
133
+ "filename" => "test.jpg",
134
+ )
129
135
 
136
+ uploaded_file
137
+ end
138
+ end
139
+ ```
140
+ <!--DOCUSAURUS_CODE_TABS-->
141
+ <!--FactoryBot-->
130
142
  ```rb
131
- # SuckerPunch
132
- require "sucker_punch/testing/inline"
143
+ factory :photo do
144
+ image_data { TestData.image_data }
145
+ end
146
+ ```
147
+ <!--Rails YAML fixtures-->
148
+ ```erb
149
+ photo:
150
+ image_data: <%= TestData.image_data %>
133
151
  ```
152
+ <!--END_DOCUSAURUS_CODE_TABS-->
153
+
154
+ ## Unit tests
155
+
156
+ For testing attachment in your unit tests, you can assign plain `File` objects:
134
157
 
135
158
  ```rb
136
- # ActiveJob
137
- ActiveJob::Base.queue_adapter = :inline
159
+ RSpec.describe ImageUploader do
160
+ let(:image) { photo.image }
161
+ let(:derivatives) { photo.image_derivatives }
162
+ let(:photo) { Photo.create(image: File.open("test/files/image.png", "rb")) }
163
+
164
+ it "extracts metadata" do
165
+ expect(image.mime_type).to eq("image/png")
166
+ expect(image.extension).to eq("png")
167
+ expect(image.size).to be_instance_of(Integer)
168
+ expect(image.width).to be_instance_of(Integer)
169
+ expect(image.height).to be_instance_of(Integer)
170
+ end
171
+
172
+ it "generates derivatives" do
173
+ expect(derivatives[:small]).to be_kind_of(Shrine::UploadedFile)
174
+ expect(derivatives[:medium]).to be_kind_of(Shrine::UploadedFile)
175
+ expect(derivatives[:large]).to be_kind_of(Shrine::UploadedFile)
176
+ end
177
+ end
138
178
  ```
139
179
 
140
180
  ## Acceptance tests
141
181
 
142
182
  In acceptance tests you're testing your app end-to-end, and you likely want to
143
- also test file attachments here. There are a variety of libraries that you
144
- might be using for your acceptance tests.
145
-
146
- ### Capybara
147
-
148
- If you're testing with the [Capybara] acceptance test framework, you can use
149
- [`#attach_file`] to select a file from your filesystem in the form:
183
+ also test file attachments here. Here are examples for some common use cases:
150
184
 
185
+ <!--DOCUSAURUS_CODE_TABS-->
186
+ <!--Capybara-->
151
187
  ```rb
152
188
  attach_file("#image-field", "test/files/image.jpg")
153
189
  ```
154
-
155
- ### Rack::Test
156
-
157
- Regular routing tests in Rails use [Rack::Test], in which case you can create
158
- `Rack::Test::UploadedFile` objects and pass them as form parameters:
159
-
190
+ <!--Rack::Test-->
160
191
  ```rb
161
- post "/photos", photo: {image: Rack::Test::UploadedFile.new("test/files/image.jpg", "image/jpeg")}
192
+ post "/photos", photo: {
193
+ image: Rack::Test::UploadedFile.new("test/files/image.jpg", "image/jpeg")
194
+ }
162
195
  ```
163
-
164
- ### Rack::TestApp
165
-
166
- With [Rack::TestApp] you can create multipart file upload requests by using the
167
- `:multipart` option and passing a `File` object:
168
-
196
+ <!--Rack::TestApp-->
169
197
  ```rb
170
- http.post "/photos", multipart: {"photo[image]" => File.open("test/files/image.jpg")}
198
+ app.post "/photos", multipart: {
199
+ "photo[image]" => File.open("test/files/image.jpg")
200
+ }
171
201
  ```
202
+ <!--END_DOCUSAURUS_CODE_TABS-->
172
203
 
173
- ## Attachment
174
-
175
- Even though all the file attachment logic is usually encapsulated in your
176
- uploader classes, in general it's still best to test this logic through models.
204
+ ## Background jobs
177
205
 
178
- In your controller the attachment attribute using the uploaded file from the
179
- controller, in Rails case it's an `ActionDispatch::Http::UploadedFile`.
180
- However, you can also assign plain `File` objects, or any other kind of IO-like
181
- objects.
206
+ If you're using background jobs with Shrine, you probably want to make them
207
+ synchronous in tests. See your backgrounding library docs for how to make jobs
208
+ synchronous.
182
209
 
210
+ <!--DOCUSAURUS_CODE_TABS-->
211
+ <!--ActiveJob-->
183
212
  ```rb
184
- describe ImageUploader do
185
- it "generates image thumbnails" do
186
- photo = Photo.create(image: File.open("test/files/image.png"))
187
- assert_equal [:small, :medium, :large], photo.image.keys
188
- end
189
- end
213
+ ActiveJob::Base.queue_adapter = :inline
190
214
  ```
191
-
192
- If you want test with an IO object that closely resembles the kind of IO that
193
- is assigned by your web framework, you can use this:
194
-
215
+ <!--Sidekiq-->
195
216
  ```rb
196
- require "forwardable"
197
- require "stringio"
198
-
199
- class FakeIO
200
- attr_reader :original_filename, :content_type
201
-
202
- def initialize(content, filename: nil, content_type: nil)
203
- @io = StringIO.new(content)
204
- @original_filename = filename
205
- @content_type = content_type
206
- end
207
-
208
- extend Forwardable
209
- delegate %i[read rewind eof? close size] => :@io
210
- end
217
+ require "sidekiq/testing"
218
+ Sidekiq::Testing.inline!
211
219
  ```
212
-
220
+ <!--SuckerPunch-->
213
221
  ```rb
214
- describe ImageUploader do
215
- it "generates image thumbnails" do
216
- photo = Photo.create(image: FakeIO.new(File.read("test/files/image.png")))
217
- assert_equal [:small, :medium, :large], photo.image.keys
218
- end
219
- end
222
+ require "sucker_punch/testing/inline"
220
223
  ```
224
+ <!--END_DOCUSAURUS_CODE_TABS-->
221
225
 
222
226
  ## Processing
223
227
 
224
- In tests you usually don't want to perform processing, or at least don't want
225
- it to be performed by default (only when you're actually testing it).
226
-
227
- If you're processing only single files, you can override the `Shrine#process`
228
- method in tests to return nil:
228
+ If you're testing your attachment flow which includes processing [derivatives],
229
+ you might want to disable the processing for certain tests. You can do this by
230
+ temporarily overriding the processor:
229
231
 
230
232
  ```rb
231
- class ImageUploader
232
- def process(io, context)
233
- # don't do any processing
234
- end
235
- end
236
- ```
237
-
238
- If you're processing versions, you can override `Shrine#process` to simply
239
- return a hash of unprocessed original files:
240
-
241
- ```rb
242
- class ImageUploader
243
- def process(io, context)
244
- if context[:action] == :store
245
- {small: io.download, medium: io.download, large: io.download}
233
+ module TestMode
234
+ module_function
235
+
236
+ def disable_processing(attacher, processor_name = :default)
237
+ attacher.class.instance_exec do
238
+ original_processor = derivatives_processor
239
+ derivatives_processor(processor_name) { Hash.new }
240
+ yield
241
+ derivatives_processor(processor_name, &original_processor)
246
242
  end
247
243
  end
248
244
  end
249
245
  ```
250
-
251
- However, it's even better to design your processing code in such a way that
252
- it's easier to swap out in tests. In your *application* code you could extract
253
- processing into a single `#call`-able object, and register it inside uploader
254
- generic `opts` hash.
255
-
256
246
  ```rb
257
- class ImageUploader < Shrine
258
- opts[:processor] = ImageThumbnailsGenerator
259
-
260
- process(:store) do |io, context|
261
- opts[:processor].call(io, context)
262
- end
247
+ TestMode.disable_processing(Photo.image_attacher) do
248
+ photo = Photo.new
249
+ photo.file = File.open("test/files/image.png", "rb")
250
+ photo.save
263
251
  end
264
252
  ```
265
253
 
266
- Now in your tests you can easily swap out `ImageThumbnailsGenerator` with
267
- "fake" processing, which just returns the result in correct format (single file
268
- or hash of versions). Since the only requirement of the processor is that it
269
- responds to `#call`, we can just swap it out for a proc or a lambda:
254
+ ## Testing direct upload
255
+
256
+ If you'd like to unit-test direct upload on the server side, you can
257
+ emulate it by uploading a file to `cache` and then assigning it to the record.
270
258
 
271
259
  ```rb
272
- ImageUploader.opts[:processor] = proc do |io, context|
273
- # return unprocessed file(s)
274
- end
260
+ cached_file = Shrine.upload(some_file, :cache)
261
+ record.attachment = cached_file.to_json
275
262
  ```
276
263
 
277
- This also has the benefit of allowing you to test `ImageThumbnailsGenerator` in
278
- isolation.
279
-
280
264
  [DatabaseCleaner]: https://github.com/DatabaseCleaner/database_cleaner
281
- [shrine-memory]: https://github.com/shrinerb/shrine-memory
282
- [factory_bot]: https://github.com/thoughtbot/factory_bot
283
- [Capybara]: https://github.com/jnicklas/capybara
284
265
  [`#attach_file`]: http://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions#attach_file-instance_method
285
- [Rack::Test]: https://github.com/brynary/rack-test
286
- [Rack::TestApp]: https://github.com/kwatch/rack-test_app
287
266
  [aws-sdk-ruby stubs]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ClientStubs.html
288
267
  [MinIO]: https://min.io/
268
+ [derivatives]: https://shrinerb.com/docs/plugins/derivatives