kithe 2.0.0.pre.alpha2 → 2.0.2
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.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/app/indexing/kithe/indexable/record_index_updater.rb +1 -1
- data/app/jobs/kithe/create_derivatives_job.rb +2 -2
- data/app/models/kithe/asset.rb +82 -154
- data/app/models/kithe/asset/derivative_creator.rb +32 -62
- data/app/models/kithe/asset/derivative_definition.rb +12 -13
- data/app/models/kithe/asset/set_shrine_uploader.rb +64 -0
- data/app/models/kithe/collection.rb +0 -6
- data/app/models/kithe/model.rb +0 -21
- data/app/models/kithe/work.rb +0 -5
- data/app/uploaders/kithe/asset_uploader.rb +15 -78
- data/lib/kithe.rb +22 -20
- data/{app/models → lib}/kithe/config_base.rb +6 -1
- data/lib/kithe/engine.rb +14 -3
- data/lib/kithe/indexable_settings.rb +1 -1
- data/lib/kithe/patch_fx.rb +39 -0
- data/lib/kithe/version.rb +4 -1
- data/lib/shrine/plugins/kithe_checksum_signatures.rb +41 -0
- data/lib/shrine/plugins/kithe_controllable_backgrounding.rb +53 -0
- data/lib/shrine/plugins/kithe_derivative_definitions.rb +101 -0
- data/lib/shrine/plugins/kithe_derivatives.rb +54 -0
- data/lib/shrine/plugins/kithe_determine_mime_type.rb +39 -0
- data/lib/shrine/plugins/kithe_persisted_derivatives.rb +161 -0
- data/lib/shrine/plugins/kithe_promotion_callbacks.rb +4 -0
- data/lib/shrine/plugins/kithe_promotion_directives.rb +33 -3
- data/lib/shrine/plugins/kithe_storage_location.rb +53 -4
- data/lib/tasks/kithe_tasks.rake +22 -15
- data/spec/dummy/app/models/plain_active_record.rb +3 -0
- data/spec/dummy/config/database.yml +6 -0
- data/spec/dummy/db/schema.rb +102 -0
- data/spec/dummy/log/development.log +3616 -0
- data/spec/dummy/log/test.log +86464 -0
- data/spec/dummy/tmp/development_secret.txt +1 -1
- data/spec/indexing/indexable_spec.rb +1 -1
- data/spec/models/kithe/asset/asset_derivatives_spec.rb +137 -0
- data/spec/models/kithe/asset/asset_promotion_hooks_spec.rb +26 -5
- data/spec/models/kithe/asset/set_shrine_uploader_spec.rb +39 -0
- data/spec/models/kithe/asset_spec.rb +9 -59
- data/spec/models/kithe/model_spec.rb +0 -32
- data/spec/models/kithe_spec.rb +10 -0
- data/spec/shrine/kithe_accept_remote_url_spec.rb +49 -0
- data/spec/shrine/kithe_checksum_signatures_spec.rb +63 -0
- data/spec/shrine/kithe_derivative_definitions_spec.rb +303 -0
- data/spec/shrine/kithe_persisted_derivatives_spec.rb +424 -0
- data/spec/shrine/kithe_storage_location_spec.rb +43 -15
- data/spec/spec_helper.rb +0 -19
- data/spec/test_support/images/3x3_pixel.jpg +0 -0
- data/spec/test_support/shrine_spec_support.rb +2 -1
- metadata +60 -36
- data/app/models/kithe/asset/derivative_updater.rb +0 -119
- data/app/models/kithe/derivative.rb +0 -15
- data/app/uploaders/kithe/derivative_uploader.rb +0 -48
- data/spec/dummy/db/structure.sql +0 -309
- data/spec/models/kithe/asset/asset_create_derivatives_spec.rb +0 -320
- data/spec/models/kithe/derivative_spec.rb +0 -168
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
require 'shrine/plugins/kithe_checksum_signatures'
|
3
|
+
|
4
|
+
# This kithe plugin is optional, let's make sure it works how we expect
|
5
|
+
describe Shrine::Plugins::KitheChecksumSignatures, queue_adpater: :inline do
|
6
|
+
temporary_class("ChecksumUploader") do
|
7
|
+
Class.new(Kithe::AssetUploader) do
|
8
|
+
plugin :kithe_checksum_signatures
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
temporary_class("ChecksumAsset") do
|
13
|
+
Class.new(Kithe::Asset) do
|
14
|
+
set_shrine_uploader(ChecksumUploader)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
around do |example|
|
19
|
+
original = Kithe::Asset.promotion_directives
|
20
|
+
Kithe::Asset.promotion_directives = { promote: :inline }
|
21
|
+
|
22
|
+
example.run
|
23
|
+
|
24
|
+
Kithe::Asset.promotion_directives = original
|
25
|
+
end
|
26
|
+
|
27
|
+
it "provides checksum metadata after promotion" do
|
28
|
+
asset = ChecksumAsset.create!(title: "test", file: StringIO.new("test"))
|
29
|
+
asset.reload
|
30
|
+
|
31
|
+
expect(asset).to be_stored
|
32
|
+
expect(asset.file.metadata.slice("md5", "sha1", "sha512")).to all(be_present)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "without promotion" do
|
36
|
+
around do |example|
|
37
|
+
original = Kithe::Asset.promotion_directives
|
38
|
+
Kithe::Asset.promotion_directives = { promote: false }
|
39
|
+
|
40
|
+
example.run
|
41
|
+
|
42
|
+
Kithe::Asset.promotion_directives = original
|
43
|
+
end
|
44
|
+
|
45
|
+
it "does not extract checksum metadata on cache" do
|
46
|
+
asset = ChecksumAsset.create!(title: "test", file: StringIO.new("test"))
|
47
|
+
asset.reload
|
48
|
+
|
49
|
+
expect(asset).not_to be_stored
|
50
|
+
expect(asset.file.metadata.slice("md5", "sha1", "sha512")).not_to include(be_present)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "derivatives" do
|
55
|
+
it "do not get checksum metadata" do
|
56
|
+
asset = ChecksumAsset.create!(title: "test", file: StringIO.new("test"))
|
57
|
+
asset.update_derivative("test", StringIO.new("test deriv"))
|
58
|
+
|
59
|
+
expect(asset.file_derivatives[:test]).to be_present
|
60
|
+
expect(asset.file_derivatives[:test].metadata.slice("md5", "sha1", "sha512")).not_to include(be_present)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
# We just test with a Kithe::Asset class, too much trouble to try to isolate, not
|
4
|
+
# worth it I think.
|
5
|
+
describe "Shrine::Plugins::KitheDerivativeDefinitions", queue_adapter: :test do
|
6
|
+
# promotion inline, disable auto derivatives
|
7
|
+
around do |example|
|
8
|
+
original = Kithe::Asset.promotion_directives
|
9
|
+
Kithe::Asset.promotion_directives = { promote: :inline, create_derivatives: false }
|
10
|
+
|
11
|
+
example.run
|
12
|
+
Kithe::Asset.promotion_directives = original
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:a_jpg_deriv_file) { Kithe::Engine.root.join("spec/test_support/images/2x2_pixel.jpg") }
|
16
|
+
|
17
|
+
temporary_class("CustomUploader") do
|
18
|
+
deriv_src_path = a_jpg_deriv_file
|
19
|
+
|
20
|
+
Class.new(Kithe::AssetUploader) do
|
21
|
+
self::Attacher.define_derivative(:some_data) do |original_file|
|
22
|
+
StringIO.new("some one data")
|
23
|
+
end
|
24
|
+
|
25
|
+
self::Attacher.define_derivative(:a_jpg) do |original_file|
|
26
|
+
FileUtils.cp(deriv_src_path,
|
27
|
+
Kithe::Engine.root.join("spec/test_support/images/2x2_pixel-TEMP.jpg"))
|
28
|
+
|
29
|
+
File.open(Kithe::Engine.root.join("spec/test_support/images/2x2_pixel-TEMP.jpg"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
temporary_class("CustomAsset") do
|
35
|
+
Class.new(Kithe::Asset) do
|
36
|
+
set_shrine_uploader(CustomUploader)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:asset) do
|
41
|
+
CustomAsset.create(title: "test",
|
42
|
+
file: File.open(Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg"))
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "normalizes string key to symbol" do
|
47
|
+
CustomUploader::Attacher.define_derivative("started_string") { |io| }
|
48
|
+
expect(CustomUploader::Attacher.kithe_derivative_definitions.collect(&:key)).to include(:started_string)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "builds derivatives" do
|
52
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
53
|
+
|
54
|
+
one_deriv = asset.file_derivatives[:some_data]
|
55
|
+
expect(one_deriv).to be_present
|
56
|
+
expect(one_deriv.read).to eq("some one data")
|
57
|
+
|
58
|
+
jpg_deriv = asset.file_derivatives[:a_jpg]
|
59
|
+
expect(jpg_deriv.read).to eq(File.binread(a_jpg_deriv_file))
|
60
|
+
expect(jpg_deriv.storage_key).to eq(:kithe_derivatives)
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "attacher argument to block" do
|
64
|
+
let(:monitoring_proc) do
|
65
|
+
proc do |original_file, attacher:|
|
66
|
+
expect(original_file.kind_of?(File) || original_file.kind_of?(Tempfile)).to be(true)
|
67
|
+
expect(original_file.path).to be_present
|
68
|
+
expect(original_file.read).to eq(asset.file.read)
|
69
|
+
|
70
|
+
expect(attacher).to be_present
|
71
|
+
expect(attacher).to be_kind_of(Shrine::Attacher)
|
72
|
+
expect(attacher.record).to eq(asset)
|
73
|
+
expect(attacher.file).to be_kind_of(Shrine::UploadedFile)
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
before do
|
79
|
+
# hacky confusing way to set this up for testing, sorry.
|
80
|
+
CustomUploader::Attacher.kithe_derivative_definitions = []
|
81
|
+
CustomUploader::Attacher.define_derivative(:some_data, &monitoring_proc)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "as expected" do
|
85
|
+
expect(monitoring_proc).to receive(:call).and_call_original
|
86
|
+
|
87
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
88
|
+
expect(asset.file_derivatives.length).to eq(0)
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "as **kwargs" do
|
92
|
+
let(:monitoring_proc) do
|
93
|
+
proc do |original_file, **kwargs|
|
94
|
+
expect(original_file.kind_of?(File) || original_file.kind_of?(Tempfile)).to be(true)
|
95
|
+
expect(original_file.path).to be_present
|
96
|
+
expect(original_file.read).to eq(asset.file.read)
|
97
|
+
|
98
|
+
# It really has to be a local file with a path, not just an IO.
|
99
|
+
# Kithe wants to guarantee this, whether or not shrine does.
|
100
|
+
expect(original_file).to respond_to(:path)
|
101
|
+
|
102
|
+
expect(kwargs[:attacher]).to be_present
|
103
|
+
expect(kwargs[:attacher]).to eq(asset.file_attacher)
|
104
|
+
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "as expected" do
|
110
|
+
expect(monitoring_proc).to receive(:call).and_call_original
|
111
|
+
|
112
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
113
|
+
expect(asset.file_derivatives.length).to eq(0)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
describe "default_create false" do
|
120
|
+
let(:monitoring_proc) { proc { |asset| } }
|
121
|
+
|
122
|
+
before do
|
123
|
+
# hacky confusing way to set this up for testing, sorry.
|
124
|
+
CustomUploader::Attacher.kithe_derivative_definitions = []
|
125
|
+
CustomUploader::Attacher.define_derivative(:some_data, default_create: false, &monitoring_proc)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "is not run automatically" do
|
129
|
+
expect(monitoring_proc).not_to receive(:call)
|
130
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "only/except" do
|
135
|
+
let(:monitoring_proc1) { proc { |asset| StringIO.new("one") } }
|
136
|
+
let(:monitoring_proc2) { proc { |asset| StringIO.new("two") } }
|
137
|
+
let(:monitoring_proc3) { proc { |asset| StringIO.new("three") } }
|
138
|
+
|
139
|
+
before do
|
140
|
+
# hacky confusing way to set this up for testing, sorry.
|
141
|
+
CustomUploader::Attacher.kithe_derivative_definitions = []
|
142
|
+
CustomUploader::Attacher.define_derivative(:one, default_create: false, &monitoring_proc1)
|
143
|
+
CustomUploader::Attacher.define_derivative(:two, &monitoring_proc2)
|
144
|
+
CustomUploader::Attacher.define_derivative(:three, &monitoring_proc2)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "can call with only" do
|
148
|
+
expect(monitoring_proc1).to receive(:call).and_call_original
|
149
|
+
expect(monitoring_proc2).to receive(:call).and_call_original
|
150
|
+
expect(monitoring_proc3).not_to receive(:call)
|
151
|
+
|
152
|
+
# except string or symbol
|
153
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives, only: [:one, "two"])
|
154
|
+
|
155
|
+
expect(asset.file_derivatives.keys).to match([:one, :two])
|
156
|
+
end
|
157
|
+
|
158
|
+
it "can call with except" do
|
159
|
+
expect(monitoring_proc1).not_to receive(:call)
|
160
|
+
expect(monitoring_proc2).to receive(:call).and_call_original
|
161
|
+
expect(monitoring_proc3).not_to receive(:call)
|
162
|
+
|
163
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives, except: [:three])
|
164
|
+
|
165
|
+
# :one was default_create:false, and we said except: :three
|
166
|
+
expect(asset.file_derivatives.keys).to eq([:two])
|
167
|
+
end
|
168
|
+
|
169
|
+
it "can call with except as string" do
|
170
|
+
expect(monitoring_proc1).not_to receive(:call)
|
171
|
+
expect(monitoring_proc2).to receive(:call).and_call_original
|
172
|
+
expect(monitoring_proc3).not_to receive(:call)
|
173
|
+
|
174
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives, except: ["three"])
|
175
|
+
|
176
|
+
# :one was default_create:false, and we said except: :three
|
177
|
+
expect(asset.file_derivatives.keys).to eq([:two])
|
178
|
+
end
|
179
|
+
|
180
|
+
it "can call with only and except" do
|
181
|
+
expect(monitoring_proc1).to receive(:call).and_call_original
|
182
|
+
expect(monitoring_proc2).to receive(:call).and_call_original
|
183
|
+
expect(monitoring_proc3).not_to receive(:call)
|
184
|
+
|
185
|
+
# string version of except why not
|
186
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives, only: [:one, :two], except: :three)
|
187
|
+
|
188
|
+
expect(asset.file_derivatives.keys).to eq([:one, :two])
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
describe "content_type filters" do
|
194
|
+
before do
|
195
|
+
# hacky confusing way to set this up for testing, sorry.
|
196
|
+
CustomUploader::Attacher.kithe_derivative_definitions = []
|
197
|
+
CustomUploader::Attacher.define_derivative(:never_called, content_type: "nothing/nothing") { |o| StringIO.new("never") }
|
198
|
+
CustomUploader::Attacher.define_derivative(:gated_positive, content_type: "image/jpeg") { |o| StringIO.new("gated positive") }
|
199
|
+
CustomUploader::Attacher.define_derivative(:gated_positive_main_type, content_type: "image") { |o| StringIO.new("gated positive") }
|
200
|
+
end
|
201
|
+
|
202
|
+
it "does not call if content type does not match" do
|
203
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
204
|
+
expect(asset.file_derivatives.keys).not_to include(:never_called)
|
205
|
+
end
|
206
|
+
|
207
|
+
it "calls for exact content type match" do
|
208
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
209
|
+
expect(asset.file_derivatives.keys).to include(:gated_positive)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "calls for main content type match" do
|
213
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
214
|
+
expect(asset.file_derivatives.keys).to include(:gated_positive_main_type)
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "as array" do
|
218
|
+
before do
|
219
|
+
# hacky confusing way to set this up for testing, sorry.
|
220
|
+
CustomUploader::Attacher.kithe_derivative_definitions = []
|
221
|
+
CustomUploader::Attacher.define_derivative(:never_called, content_type: ["nothing/nothing", "also/nothing"]) { |o| StringIO.new("never") }
|
222
|
+
CustomUploader::Attacher.define_derivative(:gated_positive, content_type: ["image/jpeg", "something/else"]) { |o| StringIO.new("gated positive") }
|
223
|
+
end
|
224
|
+
|
225
|
+
it "calls for one match" do
|
226
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
227
|
+
expect(asset.file_derivatives.keys).to eq([:gated_positive])
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "conflicting types" do
|
232
|
+
let(:unfiltered) { proc { |asset| StringIO.new("unfiltered") } }
|
233
|
+
let(:image) { proc { |asset| StringIO.new("image") } }
|
234
|
+
let(:image_jpeg) { proc { |asset| StringIO.new("image/jpeg") } }
|
235
|
+
|
236
|
+
before do
|
237
|
+
# hacky confusing way to set this up for testing, sorry.
|
238
|
+
CustomUploader::Attacher.kithe_derivative_definitions = []
|
239
|
+
CustomUploader::Attacher.define_derivative(:key, &unfiltered)
|
240
|
+
CustomUploader::Attacher.define_derivative(:key, content_type: "image/jpeg", &image_jpeg)
|
241
|
+
CustomUploader::Attacher.define_derivative(:key, content_type: "image", &image)
|
242
|
+
end
|
243
|
+
|
244
|
+
it "takes most specific" do
|
245
|
+
expect(unfiltered).not_to receive(:call)
|
246
|
+
expect(image).not_to receive(:call)
|
247
|
+
expect(image_jpeg).to receive(:call).and_call_original
|
248
|
+
|
249
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives)
|
250
|
+
expect(asset.file_derivatives.count).to eq(1)
|
251
|
+
|
252
|
+
|
253
|
+
expect(asset.file_derivatives.keys).to eq([:key])
|
254
|
+
expect(asset.file_derivatives[:key].read). to eq("image/jpeg")
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe "lazy creation" do
|
260
|
+
before do
|
261
|
+
# Create existing derivatives for existing definitions, which we assume exist
|
262
|
+
expect(CustomUploader::Attacher.kithe_derivative_definitions).to be_present
|
263
|
+
|
264
|
+
CustomUploader::Attacher.kithe_derivative_definitions.collect(&:key).each do |key|
|
265
|
+
asset.file_attacher.add_persisted_derivatives({key => StringIO.new("#{key} original")})
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
it "does not re-create" do
|
270
|
+
derivatives_pre_creation = asset.file_derivatives
|
271
|
+
|
272
|
+
asset.file_attacher.create_derivatives(:kithe_derivatives, lazy: true)
|
273
|
+
derivatives_post_creation = asset.file_derivatives
|
274
|
+
|
275
|
+
expect(derivatives_post_creation).to eq(derivatives_pre_creation)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe "#remove_derivative_definition!" do
|
280
|
+
let(:defined_derivative_key) do
|
281
|
+
CustomUploader::Attacher.defined_derivative_keys.first.tap do |key|
|
282
|
+
expect(key).to be_present
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
it "can remove by string" do
|
287
|
+
expect {
|
288
|
+
CustomUploader::Attacher.remove_derivative_definition!(defined_derivative_key.to_s)
|
289
|
+
}.to change { CustomUploader::Attacher.defined_derivative_keys.count }.from(2).to(1)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "can remove by symbol" do
|
293
|
+
expect {
|
294
|
+
CustomUploader::Attacher.remove_derivative_definition!(defined_derivative_key.to_sym)
|
295
|
+
}.to change { CustomUploader::Attacher.defined_derivative_keys.count }.from(2).to(1)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "can remove multiple args" do
|
299
|
+
CustomUploader::Attacher.remove_derivative_definition!(*CustomUploader::Attacher.defined_derivative_keys)
|
300
|
+
expect(CustomUploader::Attacher.defined_derivative_keys).to eq([])
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
@@ -0,0 +1,424 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
require 'shrine/plugins/kithe_persisted_derivatives'
|
3
|
+
|
4
|
+
# We just test with a Kithe::Asset class, too much trouble to try to isolate, not
|
5
|
+
# worth it I think.
|
6
|
+
describe Shrine::Plugins::KithePersistedDerivatives, queue_adapter: :test do
|
7
|
+
# promotion inline, disable auto derivatives
|
8
|
+
around do |example|
|
9
|
+
original = Kithe::Asset.promotion_directives
|
10
|
+
Kithe::Asset.promotion_directives = { promote: :inline, create_derivatives: false }
|
11
|
+
|
12
|
+
example.run
|
13
|
+
Kithe::Asset.promotion_directives = original
|
14
|
+
end
|
15
|
+
|
16
|
+
# Need to make a new copy, because shrine likes deleting derivatives!
|
17
|
+
def sample_deriv_file!(path = Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg"))
|
18
|
+
tempfile = Tempfile.new
|
19
|
+
IO.copy_stream(File.open(path), tempfile)
|
20
|
+
|
21
|
+
tempfile
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:sample_orig_path) { Kithe::Engine.root.join("spec/test_support/images/2x2_pixel.jpg") }
|
25
|
+
let(:another_sample_orig_path) { Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg") }
|
26
|
+
|
27
|
+
let(:asset) { Kithe::Asset.create!(title: "test", file: File.open(sample_orig_path))}
|
28
|
+
|
29
|
+
describe "#add_persisted_derivatives" do
|
30
|
+
it "can add and persist" do
|
31
|
+
asset.file_attacher.add_persisted_derivatives(sample: sample_deriv_file!)
|
32
|
+
|
33
|
+
expect(asset.changed?).to be(false)
|
34
|
+
expect(asset.file_derivatives[:sample]).to be_present
|
35
|
+
expect(asset.file_derivatives[:sample].storage_key).to eq(:kithe_derivatives)
|
36
|
+
expect(asset.file_derivatives[:sample].exists?).to be(true)
|
37
|
+
|
38
|
+
# sanity check
|
39
|
+
asset.reload
|
40
|
+
expect(asset.file_derivatives[:sample]).to be_present
|
41
|
+
end
|
42
|
+
|
43
|
+
it "can avoid deleting deriv file" do
|
44
|
+
file = sample_deriv_file!
|
45
|
+
asset.file_attacher.add_persisted_derivatives({sample: file}, delete: false)
|
46
|
+
|
47
|
+
expect(File.exists?(file.path)).to eq(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "can use custom storage" do
|
51
|
+
file = sample_deriv_file!
|
52
|
+
asset.file_attacher.add_persisted_derivatives({sample: file}, storage: :cache)
|
53
|
+
|
54
|
+
asset.reload
|
55
|
+
expect(asset.file_derivatives[:sample]).to be_present
|
56
|
+
expect(asset.file_derivatives[:sample].storage_key).to eq(:cache)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "can supply custom metadata" do
|
60
|
+
file = sample_deriv_file!
|
61
|
+
asset.file_attacher.add_persisted_derivatives({sample: file}, metadata: { extra: "value" })
|
62
|
+
|
63
|
+
asset.reload
|
64
|
+
|
65
|
+
expect(asset.file_derivatives[:sample].metadata["extra"]).to eq("value")
|
66
|
+
# and still has default metadata
|
67
|
+
expect(asset.file_derivatives[:sample].metadata["size"]).to be_present
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "model with unsaved changes" do
|
71
|
+
before do
|
72
|
+
asset.title = "changed title"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "will refuse" do
|
76
|
+
expect {
|
77
|
+
asset.file_attacher.add_persisted_derivatives(sample: sample_deriv_file!)
|
78
|
+
}.to raise_error(TypeError)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "can be forced" do
|
82
|
+
asset.file_attacher.add_persisted_derivatives({sample: sample_deriv_file!}, allow_other_changes: true)
|
83
|
+
|
84
|
+
expect(asset.changed?).to be(false)
|
85
|
+
asset.reload
|
86
|
+
expect(asset.title).to eq("changed title")
|
87
|
+
expect(asset.file_derivatives[:sample]).to be_present
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "unsaved model" do
|
92
|
+
let(:asset) { Kithe::Asset.new(title: "test", file: File.open(sample_orig_path)) }
|
93
|
+
|
94
|
+
it "refuses even with other_changes: true" do
|
95
|
+
expect {
|
96
|
+
asset.file_attacher.add_persisted_derivatives({sample: sample_deriv_file!}, allow_other_changes: true)
|
97
|
+
}.to raise_error(TypeError)
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "with an existing derivative" do
|
101
|
+
before do
|
102
|
+
asset.save!
|
103
|
+
asset.file_attacher.add_derivative("key", StringIO.new("existing"))
|
104
|
+
asset.save!
|
105
|
+
end
|
106
|
+
|
107
|
+
it "replaces" do
|
108
|
+
existing_storage = asset.file_derivatives[:key]
|
109
|
+
expect(existing_storage.exists?).to be(true)
|
110
|
+
|
111
|
+
asset.file_attacher.add_persisted_derivatives({"key" => StringIO.new("new")})
|
112
|
+
expect(asset.file_derivatives[:key].read).to eq("new")
|
113
|
+
expect(existing_storage.exists?).to be(false)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "Original deleted before derivatives can be created" do
|
119
|
+
before do
|
120
|
+
# delete it out from under us
|
121
|
+
Kithe::Model.where(id: asset.id).delete_all
|
122
|
+
end
|
123
|
+
|
124
|
+
it "doesn't complain and cleans up file" do
|
125
|
+
|
126
|
+
# asset is no longer in the DB.
|
127
|
+
# Let's try and create derivatives for it:
|
128
|
+
file = sample_deriv_file!
|
129
|
+
local_file_path = file.path
|
130
|
+
|
131
|
+
expect(asset.file_attacher.add_persisted_derivatives(sample: file)).to be(false)
|
132
|
+
|
133
|
+
expect(File.exist?(local_file_path)).to be(false)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "Original changed before derivatives can be created" do
|
138
|
+
before do
|
139
|
+
asset # load
|
140
|
+
|
141
|
+
# Change what's in the db for this asset, without changing the in-memory
|
142
|
+
# asset
|
143
|
+
another_copy = Kithe::Asset.find(asset.id)
|
144
|
+
another_copy.file = File.open(another_sample_orig_path)
|
145
|
+
another_copy.save!
|
146
|
+
end
|
147
|
+
|
148
|
+
it "doesn't add derivative and cleans up file" do
|
149
|
+
# asset in DB has different file attachment
|
150
|
+
# Let's try and create derivatives for it:
|
151
|
+
file = sample_deriv_file!
|
152
|
+
local_file_path = file.path
|
153
|
+
|
154
|
+
expect(asset.file_attacher.add_persisted_derivatives(new_try: file)).to be(false)
|
155
|
+
|
156
|
+
|
157
|
+
expect(asset.changed?).to be(false)
|
158
|
+
expect(asset.file_derivatives[:new_try]).to be_nil
|
159
|
+
asset.reload
|
160
|
+
expect(asset.file_derivatives[:new_try]).to be_nil
|
161
|
+
|
162
|
+
expect(File.exist?(local_file_path)).to be(false)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "concurrent derivative changes" do
|
167
|
+
let(:original_one) { sample_deriv_file!(Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg")) }
|
168
|
+
let(:original_two) { sample_deriv_file!(Kithe::Engine.root.join("spec/test_support/images/2x2_pixel.jpg")) }
|
169
|
+
|
170
|
+
let(:new_two) { sample_deriv_file!(Kithe::Engine.root.join("spec/test_support/images/3x3_pixel.jpg")) }
|
171
|
+
let(:new_three) { sample_deriv_file!(Kithe::Engine.root.join("spec/test_support/images/3x3_pixel.jpg")) }
|
172
|
+
|
173
|
+
before do
|
174
|
+
# make sure our test is setup to test what we want
|
175
|
+
original_two.rewind; new_two.rewind
|
176
|
+
expect(original_two.read).not_to eq(new_two.read)
|
177
|
+
original_two.rewind; new_two.rewind
|
178
|
+
|
179
|
+
asset # load
|
180
|
+
|
181
|
+
# change what derivatives are in db for this asset, without changing
|
182
|
+
# the in-memory asset
|
183
|
+
another_copy = Kithe::Asset.find(asset.id)
|
184
|
+
another_copy.file_attacher.add_derivatives({
|
185
|
+
one: original_one,
|
186
|
+
two: original_two
|
187
|
+
}, delete: false)
|
188
|
+
another_copy.save!
|
189
|
+
|
190
|
+
# Make sure we set up what we expected
|
191
|
+
another_copy.reload
|
192
|
+
expect(another_copy.file_derivatives[:one]).to be_present
|
193
|
+
expect(another_copy.file_derivatives[:two]).to be_present
|
194
|
+
end
|
195
|
+
|
196
|
+
it "merges changes in safely" do
|
197
|
+
expect(asset.file_derivatives.keys).to be_empty
|
198
|
+
|
199
|
+
asset.file_attacher.add_persisted_derivatives({two: new_two, three: new_three}, delete: false)
|
200
|
+
|
201
|
+
expect(asset.changed?).to be(false)
|
202
|
+
expect(asset.file_derivatives.keys).to match([:one, :two, :three])
|
203
|
+
expect(asset.file_derivatives[:two].read).to eq(File.binread(new_two.path))
|
204
|
+
expect(asset.file_derivatives[:three].read).to eq(File.binread(new_three.path))
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "#create_persisted_derivatives" do
|
210
|
+
temporary_class("AssetSubclassUploader") do
|
211
|
+
call_fakeio = method(:fakeio) # weird closure issue
|
212
|
+
|
213
|
+
Class.new(Kithe::AssetUploader) do
|
214
|
+
self::Attacher.derivatives do |original, **options|
|
215
|
+
{
|
216
|
+
one: call_fakeio.("one"),
|
217
|
+
original_reflected: call_fakeio.(original.read)
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
self::Attacher.derivatives(:options) do |original, **options|
|
222
|
+
{
|
223
|
+
options_one: call_fakeio.("one"),
|
224
|
+
options_reflected: call_fakeio.(options.to_s)
|
225
|
+
}
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
temporary_class("AssetSubclass") do
|
231
|
+
Class.new(Kithe::Asset) do
|
232
|
+
set_shrine_uploader(AssetSubclassUploader)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
let(:asset) { AssetSubclass.create!(title: "test", file: File.open(sample_orig_path))}
|
237
|
+
|
238
|
+
it "creates derivatives" do
|
239
|
+
# we're not gonna test concurrency safety, counting on add_persisted_derivatives
|
240
|
+
# for that, but let's make sure
|
241
|
+
expect(asset.file_attacher).to receive(:add_persisted_derivatives).and_call_original
|
242
|
+
|
243
|
+
asset.file_attacher.create_persisted_derivatives
|
244
|
+
|
245
|
+
expect(asset.changed?).to be(false)
|
246
|
+
expect(asset.file_derivatives.keys).to match([:one, :original_reflected])
|
247
|
+
asset.reload
|
248
|
+
expect(asset.file_derivatives[:one].read).to eq("one")
|
249
|
+
expect(asset.file_derivatives[:one].storage_key).to eq(:kithe_derivatives)
|
250
|
+
expect(asset.file_derivatives[:original_reflected].read).to eq(File.binread(sample_orig_path))
|
251
|
+
expect(asset.file_derivatives[:original_reflected].storage_key).to eq(:kithe_derivatives)
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "with custom source" do
|
255
|
+
let(:string_io_source) { StringIO.new("pretend data") }
|
256
|
+
|
257
|
+
it "works with custom source as StringIO" do
|
258
|
+
asset.file_attacher.create_persisted_derivatives(:options, string_io_source)
|
259
|
+
expect(asset.file_derivatives).to be_present
|
260
|
+
end
|
261
|
+
|
262
|
+
it "works with custom source StringIO as only arg" do
|
263
|
+
asset.file_attacher.create_persisted_derivatives(string_io_source)
|
264
|
+
|
265
|
+
string_io_source.rewind
|
266
|
+
expect(asset.file_derivatives[:original_reflected].read).to eq(string_io_source.read)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe "for an asset with nil file_data" do
|
271
|
+
let(:asset) { AssetSubclass.create!(title: "blank") }
|
272
|
+
|
273
|
+
it "no-ops" do
|
274
|
+
expect(asset.file_attacher.create_persisted_derivatives).to be(false)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "for an asset with missing original" do
|
279
|
+
let(:asset) { AssetSubclass.create!(title: "blank", file_data: { storage: "cache", id: "not_found"}) }
|
280
|
+
|
281
|
+
it "raises" do
|
282
|
+
expect(asset.file.exists?).to be(false)
|
283
|
+
|
284
|
+
# Not necessarily what kithe 1.x did, but this seems better...
|
285
|
+
expect {
|
286
|
+
asset.file_attacher.create_persisted_derivatives
|
287
|
+
}.to raise_error(Shrine::FileNotFound)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
it "can call custom processor" do
|
292
|
+
asset.file_attacher.create_persisted_derivatives(:options)
|
293
|
+
|
294
|
+
expect(asset.file_derivatives.keys).to match([:options_one, :options_reflected])
|
295
|
+
end
|
296
|
+
|
297
|
+
it "can pass processor options" do
|
298
|
+
asset.file_attacher.create_persisted_derivatives(:options, arg1: "value1", arg2: "value2")
|
299
|
+
|
300
|
+
expect(asset.file_derivatives[:options_reflected].read).to eq({arg1: "value1", arg2: "value2"}.to_s)
|
301
|
+
end
|
302
|
+
|
303
|
+
it "can customize :storage" do
|
304
|
+
asset.file_attacher.create_persisted_derivatives(:options, storage: :cache, arg1: "value1", arg2: "value2")
|
305
|
+
|
306
|
+
expect(asset.file_derivatives[:options_reflected].read).to eq({arg1: "value1", arg2: "value2"}.to_s)
|
307
|
+
expect(asset.file_derivatives[:options_reflected].storage_key).to eq(:cache)
|
308
|
+
end
|
309
|
+
|
310
|
+
describe "model with unsaved changes" do
|
311
|
+
before do
|
312
|
+
asset.title = "changed title"
|
313
|
+
end
|
314
|
+
|
315
|
+
it "will refuse" do
|
316
|
+
expect {
|
317
|
+
asset.file_attacher.create_persisted_derivatives
|
318
|
+
}.to raise_error(TypeError)
|
319
|
+
end
|
320
|
+
|
321
|
+
it "can be forced" do
|
322
|
+
asset.file_attacher.create_persisted_derivatives(allow_other_changes: true)
|
323
|
+
|
324
|
+
expect(asset.changed?).to be(false)
|
325
|
+
asset.reload
|
326
|
+
expect(asset.title).to eq("changed title")
|
327
|
+
expect(asset.file_derivatives.keys).to match([:one, :original_reflected])
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
describe "#remove_persisted_derivatives" do
|
333
|
+
before do
|
334
|
+
asset.file_attacher.add_persisted_derivatives(
|
335
|
+
sample1: fakeio("sample 1"),
|
336
|
+
sample2: fakeio("sample 2")
|
337
|
+
)
|
338
|
+
end
|
339
|
+
|
340
|
+
it "can remove" do
|
341
|
+
removed = asset.file_attacher.remove_persisted_derivatives(:sample1)
|
342
|
+
|
343
|
+
expect(asset.changed?).to eq(false)
|
344
|
+
expect(asset.file_derivatives.keys).to eq([:sample2])
|
345
|
+
asset.reload
|
346
|
+
expect(asset.file_derivatives.keys).to eq([:sample2])
|
347
|
+
|
348
|
+
expect(removed).to be_kind_of(Array)
|
349
|
+
expect(removed.length).to eq(1)
|
350
|
+
expect(removed.first).to be_kind_of(Shrine::UploadedFile)
|
351
|
+
expect(removed.first.exists?).to be(false)
|
352
|
+
end
|
353
|
+
|
354
|
+
describe "if someone else removed first" do
|
355
|
+
before do
|
356
|
+
another_copy = asset.class.find(asset.id)
|
357
|
+
another_copy.file_attacher.remove_derivative(:sample1)
|
358
|
+
another_copy.save!
|
359
|
+
another_copy.reload
|
360
|
+
expect(another_copy.file_derivatives.keys).to eq([:sample2])
|
361
|
+
|
362
|
+
expect(asset.file_derivatives.keys).to match([:sample1, :sample2])
|
363
|
+
end
|
364
|
+
|
365
|
+
it "doesn't complain" do
|
366
|
+
asset.file_attacher.remove_persisted_derivatives(:sample1)
|
367
|
+
expect(asset.changed?).to eq(false)
|
368
|
+
expect(asset.file_derivatives.keys).to eq([:sample2])
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "someone else added another derivative" do
|
373
|
+
before do
|
374
|
+
another_copy = asset.class.find(asset.id)
|
375
|
+
another_copy.file_attacher.add_persisted_derivatives({:sample3 => fakeio("sample 3")})
|
376
|
+
another_copy.reload
|
377
|
+
expect(another_copy.file_derivatives.keys).to match([:sample1, :sample2, :sample3])
|
378
|
+
|
379
|
+
expect(asset.file_derivatives.keys).to match([:sample1, :sample2])
|
380
|
+
end
|
381
|
+
|
382
|
+
it "deletes without deleting newly added" do
|
383
|
+
asset.file_attacher.remove_persisted_derivatives(:sample1)
|
384
|
+
|
385
|
+
expect(asset.changed?).to eq(false)
|
386
|
+
expect(asset.file_derivatives.keys).to eq([:sample2, :sample3])
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe "model deleted from under us" do
|
391
|
+
before do
|
392
|
+
another_copy = asset.class.find(asset.id)
|
393
|
+
another_copy.destroy!
|
394
|
+
end
|
395
|
+
|
396
|
+
it "silently no-ops" do
|
397
|
+
result = asset.file_attacher.remove_persisted_derivatives(:sample1)
|
398
|
+
expect(result).to eq(false)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
describe "model with unsaved changes" do
|
403
|
+
before do
|
404
|
+
asset.title = "changed title"
|
405
|
+
end
|
406
|
+
|
407
|
+
it "will refuse" do
|
408
|
+
expect {
|
409
|
+
asset.file_attacher.remove_persisted_derivatives(:sample1)
|
410
|
+
}.to raise_error(TypeError)
|
411
|
+
end
|
412
|
+
|
413
|
+
it "can be forced" do
|
414
|
+
asset.file_attacher.remove_persisted_derivatives(:sample1, allow_other_changes: true)
|
415
|
+
|
416
|
+
expect(asset.changed?).to be(false)
|
417
|
+
asset.reload
|
418
|
+
expect(asset.title).to eq("changed title")
|
419
|
+
expect(asset.file_derivatives.keys).to eq([:sample2])
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
end
|
424
|
+
end
|