kithe 2.0.0.pre.alpha2 → 2.0.0.pre.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/jobs/kithe/create_derivatives_job.rb +2 -2
  3. data/app/models/kithe/asset.rb +82 -154
  4. data/app/models/kithe/asset/derivative_creator.rb +32 -62
  5. data/app/models/kithe/asset/derivative_definition.rb +12 -13
  6. data/app/models/kithe/asset/set_shrine_uploader.rb +64 -0
  7. data/app/models/kithe/collection.rb +0 -6
  8. data/app/models/kithe/model.rb +0 -21
  9. data/app/models/kithe/work.rb +0 -5
  10. data/app/uploaders/kithe/asset_uploader.rb +15 -78
  11. data/lib/kithe/version.rb +4 -1
  12. data/lib/shrine/plugins/kithe_checksum_signatures.rb +41 -0
  13. data/lib/shrine/plugins/kithe_controllable_backgrounding.rb +53 -0
  14. data/lib/shrine/plugins/kithe_derivative_definitions.rb +101 -0
  15. data/lib/shrine/plugins/kithe_derivatives.rb +54 -0
  16. data/lib/shrine/plugins/kithe_determine_mime_type.rb +39 -0
  17. data/lib/shrine/plugins/kithe_persisted_derivatives.rb +161 -0
  18. data/lib/shrine/plugins/kithe_promotion_callbacks.rb +4 -0
  19. data/lib/shrine/plugins/kithe_promotion_directives.rb +33 -3
  20. data/lib/shrine/plugins/kithe_storage_location.rb +53 -4
  21. data/lib/tasks/kithe_tasks.rake +22 -15
  22. data/spec/dummy/log/development.log +867 -0
  23. data/spec/dummy/log/test.log +26005 -0
  24. data/spec/models/kithe/asset/asset_derivatives_spec.rb +137 -0
  25. data/spec/models/kithe/asset/asset_promotion_hooks_spec.rb +26 -5
  26. data/spec/models/kithe/asset/set_shrine_uploader_spec.rb +39 -0
  27. data/spec/models/kithe/asset_spec.rb +9 -59
  28. data/spec/models/kithe/model_spec.rb +0 -32
  29. data/spec/shrine/kithe_accept_remote_url_spec.rb +49 -0
  30. data/spec/shrine/kithe_checksum_signatures_spec.rb +63 -0
  31. data/spec/shrine/kithe_derivative_definitions_spec.rb +303 -0
  32. data/spec/shrine/kithe_persisted_derivatives_spec.rb +424 -0
  33. data/spec/shrine/kithe_storage_location_spec.rb +43 -15
  34. data/spec/spec_helper.rb +7 -6
  35. data/spec/test_support/images/3x3_pixel.jpg +0 -0
  36. data/spec/test_support/shrine_spec_support.rb +2 -1
  37. metadata +23 -23
  38. data/app/models/kithe/asset/derivative_updater.rb +0 -119
  39. data/app/models/kithe/derivative.rb +0 -15
  40. data/app/uploaders/kithe/derivative_uploader.rb +0 -48
  41. data/spec/models/kithe/asset/asset_create_derivatives_spec.rb +0 -320
  42. data/spec/models/kithe/derivative_spec.rb +0 -168
@@ -0,0 +1,137 @@
1
+ require 'rails_helper'
2
+
3
+ # our configuration, customization, and added value on top of shrine derivatives.
4
+ # https://shrinerb.com/docs/plugins/derivatives
5
+ describe "customized shrine derivatives", queue_adapter: :inline do
6
+ let(:derivative_file_path) { Kithe::Engine.root.join("spec/test_support/images/2x2_pixel.jpg") }
7
+ let(:original_file_path) { Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg") }
8
+
9
+ describe "kithe derivative definitions" do
10
+ temporary_class("CustomUploader") do
11
+ call_fakeio = method(:fakeio) # weird closure issue
12
+ deriv_path = derivative_file_path
13
+ Class.new(Kithe::AssetUploader) do
14
+ self::Attacher.define_derivative(:fixed) do |io|
15
+ call_fakeio.(File.binread(deriv_path))
16
+ end
17
+ end
18
+ end
19
+
20
+ temporary_class("CustomAsset") do
21
+ Class.new(Kithe::Asset) do
22
+ set_shrine_uploader(CustomUploader)
23
+ end
24
+ end
25
+
26
+ it "automatically sets up derivative properly" do
27
+ asset = CustomAsset.create!(title: "test", file: File.open(original_file_path))
28
+ # happened in BG job, so have to reload to see it.
29
+ asset.reload
30
+
31
+ derivative = asset.file_derivatives[:fixed]
32
+ expect(derivative).to be_present
33
+
34
+ expect(derivative.exists?).to be(true)
35
+ expect(derivative.read).to eq(File.binread(derivative_file_path))
36
+ derivative.rewind
37
+
38
+ expect(derivative.storage_key).to eq(:kithe_derivatives)
39
+
40
+ # have some expected metadata, including good constructed 'filename'
41
+ expect(derivative.metadata["size"]).to eq(File.binread(derivative_file_path).length)
42
+ expect(derivative.metadata["mime_type"]).to eq("image/jpeg")
43
+ expect(derivative.metadata["height"]).to eq(2)
44
+ expect(derivative.metadata["width"]).to eq(2)
45
+ expect(derivative.metadata["filename"]).to eq("#{asset.friendlier_id}_fixed.jpeg")
46
+
47
+ # path on storage is nice and pretty
48
+ expect(derivative.id).to match %r{\A#{asset.id}/fixed/[a-f0-9]+\.jpeg\Z}
49
+ end
50
+
51
+
52
+ it "can manually #create_derivatives" do
53
+ asset = CustomAsset.create!(title: "test", file: File.open(original_file_path))
54
+ asset.reload
55
+
56
+ asset.file_attacher.set_derivatives({})
57
+ asset.save!
58
+ asset.reload
59
+ expect(asset.file_derivatives).to be_empty
60
+
61
+ asset.create_derivatives
62
+ asset.reload
63
+ derivative = asset.file_derivatives[:fixed]
64
+ expect(derivative).to be_present
65
+
66
+ expect(derivative.exists?).to be(true)
67
+ end
68
+
69
+
70
+ it "can remove derivatives" do
71
+ asset = CustomAsset.create!(title: "test", file: File.open(original_file_path))
72
+ asset.reload
73
+
74
+ asset.remove_derivatives(:fixed)
75
+ expect(asset.file_derivatives.keys).to be_empty
76
+ asset.reload
77
+ expect(asset.file_derivatives.keys).to be_empty
78
+ end
79
+
80
+ describe "with existing derivative", queue_adapter: :inline do
81
+ let(:asset) do
82
+ asset = CustomAsset.create!(title: "test", file: File.open(original_file_path))
83
+ asset.reload
84
+ asset.create_derivatives
85
+ asset.reload
86
+ end
87
+
88
+ it "deletes stored derivative file when model is deleted" do
89
+ derivatives = asset.file_derivatives.values
90
+ expect(derivatives).to be_present
91
+
92
+ asset.destroy!
93
+ expect(derivatives.none? {|d| d.exists? }).to be(true)
94
+ end
95
+
96
+ it "deletes stored derivatives on new file assignment" do
97
+ derivatives = asset.file_derivatives.values
98
+ expect(derivatives).to be_present
99
+
100
+ asset.file = File.open(original_file_path)
101
+ asset.save!
102
+ asset.reload
103
+
104
+ expect(derivatives.none? {|d| d.exists? }).to be(true)
105
+ end
106
+
107
+ it "lazy create does not even read original" do
108
+ pre_existing = asset.file_derivatives[:fixed]
109
+
110
+ expect(asset.file).not_to receive(:read)
111
+ expect(asset.file).not_to receive(:download)
112
+
113
+ asset.create_derivatives(lazy: true)
114
+
115
+ expect(asset.file_derivatives[:fixed]).to eq(pre_existing)
116
+ end
117
+
118
+ describe "#update_derivative" do
119
+ it "can add a derivative" do
120
+ result = asset.update_derivative(:fixed, StringIO.new("test updated"))
121
+
122
+ expect(result).to be_kind_of(Shrine::UploadedFile)
123
+ expect(asset.file_derivatives[:fixed].read).to eq("test updated")
124
+ expect(asset.file_derivatives[:fixed].storage_key).to eq(:kithe_derivatives)
125
+ end
126
+
127
+ it "can add a derivative with meadata" do
128
+ result = asset.update_derivative("test", StringIO.new("test"), metadata: { "manual" => "value"} )
129
+
130
+ expect(result).to be_kind_of(Shrine::UploadedFile)
131
+ expect(asset.file_derivatives[:test].metadata["manual"]).to eq("value")
132
+ expect(asset.file_derivatives[:test].metadata["size"]).to be_present
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -3,9 +3,6 @@ require 'rails_helper'
3
3
  describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
4
4
  temporary_class("TestAsset") do
5
5
  Class.new(Kithe::Asset) do
6
- define_derivative :test do
7
- # no-op, but we need a definition so will be scheduled
8
- end
9
6
  end
10
7
  end
11
8
 
@@ -33,7 +30,6 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
33
30
  it "has access to automatic metadata extraction" do
34
31
  unsaved_asset.save!
35
32
  expect($metadata_in_before_promotion).to be_present
36
- expect($metadata_in_before_promotion['sha512']).to be_present
37
33
  end
38
34
  end
39
35
 
@@ -216,7 +212,6 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
216
212
  asset.reload
217
213
 
218
214
  expect(asset.stored?).to be(true)
219
- expect(asset.sha512).to be_present
220
215
  end
221
216
  end
222
217
 
@@ -259,6 +254,20 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
259
254
  end
260
255
 
261
256
  describe "promotion_directive :promote", queue_adapter: :test do
257
+ temporary_class("TestUploader") do
258
+ Class.new(Kithe::AssetUploader) do
259
+ self::Attacher.define_derivative :test do
260
+ # no-op, but we need a definition so will be scheduled
261
+ end
262
+ end
263
+ end
264
+
265
+ temporary_class("TestAsset") do
266
+ Class.new(Kithe::Asset) do
267
+ set_shrine_uploader(TestUploader)
268
+ end
269
+ end
270
+
262
271
  it "can cancel promotion" do
263
272
  expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:promote)
264
273
 
@@ -383,6 +392,7 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
383
392
  asset = Kithe::Asset.new
384
393
  asset.set_promotion_directives(promote: :inline)
385
394
  expect(asset.file_attacher.promotion_directives).to eq("promote" => "inline")
395
+ expect(asset.promotion_directives).to eq("promote" => "inline")
386
396
  end
387
397
 
388
398
  it "setting from instance writer is aggregative" do
@@ -391,5 +401,16 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
391
401
  asset.set_promotion_directives(create_derivatives: false)
392
402
  expect(asset.file_attacher.promotion_directives).to eq("promote" => "inline", "create_derivatives" => "false")
393
403
  end
404
+
405
+ it "setting from instance writer survives reload" do
406
+ asset = Kithe::Asset.create(title: "test")
407
+ asset.set_promotion_directives(create_derivatives: false)
408
+ expect(asset.file_attacher.promotion_directives).to eq("create_derivatives" => "false")
409
+
410
+ asset.reload
411
+
412
+ expect(asset.file_attacher.promotion_directives).to eq("create_derivatives" => "false")
413
+ end
414
+
394
415
  end
395
416
  end
@@ -0,0 +1,39 @@
1
+ require 'rails_helper'
2
+
3
+ describe Kithe::Asset::SetShrineUploader do
4
+ temporary_class("MyUploaderSubclass") do
5
+ Class.new(Kithe::AssetUploader) do
6
+ add_metadata :uploader_class_name do |io|
7
+ self.class.name
8
+ end
9
+ end
10
+ end
11
+
12
+ temporary_class("AssetSubclass") do
13
+ Class.new(Kithe::Asset) do
14
+ set_shrine_uploader(MyUploaderSubclass)
15
+ end
16
+ end
17
+
18
+ let(:asset) { AssetSubclass.create!(title: "test") }
19
+ let(:image_path) { Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg") }
20
+
21
+ it "has proper class attacher" do
22
+ expect(AssetSubclass.file_attacher.class).to eq(MyUploaderSubclass::Attacher)
23
+ end
24
+
25
+ it "has proper instance attacher" do
26
+ expect(asset.file_attacher.class).to eq(MyUploaderSubclass::Attacher)
27
+ end
28
+
29
+ it "can attach file using custom subclass" do
30
+ asset.set_promotion_directives(promote: :inline)
31
+ asset.file = File.open(image_path)
32
+ asset.save!
33
+ asset.reload
34
+
35
+ expect(asset.stored?).to eq(true)
36
+ expect(asset.file).to be_present
37
+ expect(asset.file.metadata["uploader_class_name"]).to eq("MyUploaderSubclass")
38
+ end
39
+ end
@@ -51,11 +51,6 @@ RSpec.describe Kithe::Asset, type: :model do
51
51
 
52
52
  # This is the file location/storage path, currently under UUID pk.
53
53
  expect(asset.file.id).to match %r{\Aasset/#{asset.id}/.*\.jpg}
54
-
55
- # checksums
56
- expect(asset.sha1).to eq(Digest::SHA1.hexdigest(File.open(source_path).read))
57
- expect(asset.md5).to eq(Digest::MD5.hexdigest(File.open(source_path).read))
58
- expect(asset.sha512).to eq(Digest::SHA512.hexdigest(File.open(source_path).read))
59
54
  end
60
55
 
61
56
  describe "pdf file" do
@@ -90,46 +85,9 @@ RSpec.describe Kithe::Asset, type: :model do
90
85
 
91
86
  # This is the file location/storage path, currently under UUID pk.
92
87
  expect(asset.file.id).to match %r{\Aasset/#{asset.id}/.*\.jpg}
93
-
94
- # checksums
95
- expect(asset.sha1).to eq(Digest::SHA1.hexdigest(File.open(sample_file_path).read))
96
- expect(asset.md5).to eq(Digest::MD5.hexdigest(File.open(sample_file_path).read))
97
- expect(asset.sha512).to eq(Digest::SHA512.hexdigest(File.open(sample_file_path).read))
98
88
  end
99
89
  end
100
90
 
101
- describe "remote urls", queue_adapter: :inline do
102
- it "can assign and promote" do
103
- stub_request(:any, "www.example.com/bar.html?foo=bar").
104
- to_return(body: "Example Response" )
105
-
106
- asset.file = {"id" => "http://www.example.com/bar.html?foo=bar", "storage" => "remote_url"}
107
- asset.save!
108
- asset.reload
109
-
110
- expect(asset.file.storage_key).to eq(asset.file_attacher.store.storage_key.to_sym)
111
- expect(asset.stored?).to be true
112
- expect(asset.file.read).to include("Example Response")
113
- expect(asset.file.id).to end_with(".html") # no query params
114
- end
115
-
116
- it "will fetch headers" do
117
- stubbed = stub_request(:any, "www.example.com/bar.html?foo=bar").
118
- to_return(body: "Example Response" )
119
-
120
- asset.file = {"id" => "http://www.example.com/bar.html?foo=bar",
121
- "storage" => "remote_url",
122
- "headers" => {"Authorization" => "Bearer TestToken"}}
123
-
124
- asset.save!
125
-
126
- expect(
127
- a_request(:get, "www.example.com/bar.html?foo=bar").with(
128
- headers: {'Authorization'=>'Bearer TestToken', 'User-Agent' => /.+/}
129
- )
130
- ).to have_been_made.times(1)
131
- end
132
- end
133
91
 
134
92
  describe "#promote", queue_adapter: :test do
135
93
  let(:asset) { FactoryBot.create(:kithe_asset, :with_file) }
@@ -144,7 +102,7 @@ RSpec.describe Kithe::Asset, type: :model do
144
102
  expect(asset.stored?).to be(true)
145
103
  expect(asset.file_attacher.stored?).to be(true)
146
104
  expect(asset.file.exists?).to be(true)
147
- expect(asset.file.metadata.keys).to include("filename", "size", "mime_type", "width", "height", "md5", "sha1", "sha512")
105
+ expect(asset.file.metadata.keys).to include("filename", "size", "mime_type", "width", "height")
148
106
  end
149
107
 
150
108
  it "does not do anything for already promoted file", queue_adapter: :inline do
@@ -158,15 +116,6 @@ RSpec.describe Kithe::Asset, type: :model do
158
116
  end
159
117
  end
160
118
 
161
- describe "#derivative_for" do
162
- let!(:derivative) do
163
- asset.derivatives.create!(key: "foo", file: StringIO.new("whatever"))
164
- end
165
- it "returns thing" do
166
- expect(asset.derivative_for(:foo)).to eq(derivative)
167
- end
168
- end
169
-
170
119
  describe "removes derivatives", queue_adapter: :inline do
171
120
  let(:asset_with_derivatives) do
172
121
  Kithe::Asset.create(title: "test",
@@ -178,19 +127,17 @@ RSpec.describe Kithe::Asset, type: :model do
178
127
  a.update_derivative(:existing, StringIO.new("content"))
179
128
  end
180
129
  end
181
- let!(:existing_derivative) { asset_with_derivatives.derivatives.first }
182
- let!(:existing_stored_file) { existing_derivative.file }
130
+
131
+ let!(:existing_stored_file) { asset_with_derivatives.file_derivatives.values.first }
183
132
 
184
133
  it "deletes derivatives on delete" do
185
134
  asset_with_derivatives.destroy
186
- expect{ existing_derivative.reload }.to raise_error(ActiveRecord::RecordNotFound)
187
135
  expect(existing_stored_file.exists?).to be(false)
188
136
  end
189
137
 
190
138
  it "deletes derivatives on new asset assigned" do
191
139
  asset_with_derivatives.file = StringIO.new("some new thing")
192
140
  asset_with_derivatives.save!
193
- expect{ existing_derivative.reload }.to raise_error(ActiveRecord::RecordNotFound)
194
141
  expect(existing_stored_file.exists?).to be(false)
195
142
  end
196
143
 
@@ -198,12 +145,15 @@ RSpec.describe Kithe::Asset, type: :model do
198
145
  # mostly needed for testing scenarios, not otherwise expected.
199
146
  filepath = Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg")
200
147
  asset = Kithe::Asset.new(file: File.open(filepath), title: "test").tap do |a|
201
- a.file_attacher.set_promotion_directives(skip_callbacks: true)
148
+ a.file_attacher.set_promotion_directives(promote: false, skip_callbacks: true)
202
149
  end
203
- asset.derivatives << Kithe::Derivative.new(file: File.open(filepath), key: "test")
204
150
  asset.save!
205
151
  asset.reload
206
- expect(asset.derivatives.count).to eq 1
152
+
153
+ expect(asset.stored?).to eq(false)
154
+ asset.update_derivative("test", File.open(filepath), delete: false)
155
+
156
+ expect(asset.file_derivatives.count).to eq 1
207
157
  end
208
158
  end
209
159
  end
@@ -32,18 +32,6 @@ module Kithe
32
32
  end
33
33
  end
34
34
 
35
- describe "eager-loading derivatives" do
36
- let!(:work) { FactoryBot.create(:kithe_work) }
37
- let!(:collection) { FactoryBot.create(:kithe_collection) }
38
- let!(:asset) { FactoryBot.create(:kithe_asset) }
39
-
40
- it "work from hetereogeous collections" do
41
- results = Kithe::Model.all.includes(:derivatives)
42
- asset = results.to_a.find { |a| a.kind_of? Kithe::Asset }
43
- expect(asset.derivatives.loaded?).to be(true)
44
- end
45
- end
46
-
47
35
  describe "contains association" do
48
36
  let(:collection1) { FactoryBot.create(:kithe_collection)}
49
37
  let(:collection2) { FactoryBot.create(:kithe_collection)}
@@ -72,25 +60,5 @@ module Kithe
72
60
  expect(work2.contained_by.count).to eq(0)
73
61
  end
74
62
  end
75
-
76
- describe "with_representative_derivatives scope" do
77
- let(:work) {
78
- FactoryBot.create(:kithe_work, title: "test for preload",
79
- members: [
80
- FactoryBot.create(:kithe_work, representative: FactoryBot.create(:kithe_asset, :faked_derivatives)),
81
- FactoryBot.create(:kithe_asset, :faked_derivatives),
82
- FactoryBot.create(:kithe_asset, :faked_derivatives)
83
- ])
84
- }
85
- it "pre-loads all representatives and derivatives" do
86
- members = work.members.with_representative_derivatives.to_a
87
-
88
- members.each do |member|
89
- expect(member.association(:leaf_representative)).to be_loaded
90
- expect(member.leaf_representative.association(:derivatives)).to be_loaded
91
- end
92
- end
93
- end
94
-
95
63
  end
96
64
  end
@@ -0,0 +1,49 @@
1
+ require 'rails_helper'
2
+ require 'shrine/plugins/kithe_accept_remote_url'
3
+
4
+ describe Shrine::Plugins::KitheAcceptRemoteUrl, queue_adapter: :inline do
5
+ temporary_class("RemoteUrlUploader") do
6
+ Class.new(Kithe::AssetUploader) do
7
+ plugin :kithe_accept_remote_url
8
+ end
9
+ end
10
+
11
+ temporary_class("MyAsset") do
12
+ Class.new(Kithe::Asset) do
13
+ set_shrine_uploader(RemoteUrlUploader)
14
+ end
15
+ end
16
+
17
+ let(:asset) { MyAsset.create!(title: "test") }
18
+
19
+ it "can assign and promote" do
20
+ stub_request(:any, "www.example.com/bar.html?foo=bar").
21
+ to_return(body: "Example Response" )
22
+
23
+ asset.file = {"id" => "http://www.example.com/bar.html?foo=bar", "storage" => "remote_url"}
24
+ asset.save!
25
+ asset.reload
26
+
27
+ expect(asset.file.storage_key).to eq(asset.file_attacher.store.storage_key.to_sym)
28
+ expect(asset.stored?).to be true
29
+ expect(asset.file.read).to include("Example Response")
30
+ expect(asset.file.id).to end_with(".html") # no query params
31
+ end
32
+
33
+ it "will fetch headers" do
34
+ stubbed = stub_request(:any, "www.example.com/bar.html?foo=bar").
35
+ to_return(body: "Example Response" )
36
+
37
+ asset.file = {"id" => "http://www.example.com/bar.html?foo=bar",
38
+ "storage" => "remote_url",
39
+ "headers" => {"Authorization" => "Bearer TestToken"}}
40
+
41
+ asset.save!
42
+
43
+ expect(
44
+ a_request(:get, "www.example.com/bar.html?foo=bar").with(
45
+ headers: {'Authorization'=>'Bearer TestToken', 'User-Agent' => /.+/}
46
+ )
47
+ ).to have_been_made.times(1)
48
+ end
49
+ end