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
@@ -4,29 +4,57 @@ require 'shrine/plugins/kithe_storage_location'
4
4
  describe Shrine::Plugins::KitheStorageLocation do
5
5
  let(:uploader) { test_uploader { plugin :kithe_storage_location } }
6
6
 
7
- it "uploads with a record with id" do
8
- uploaded_file = uploader.upload(fakeio, record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
7
+ describe "for main file" do
8
+ it "uploads with a record with id" do
9
+ uploaded_file = uploader.upload(fakeio, record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
9
10
 
10
- expect(uploaded_file.id).to match %r{\Aasset/81060886-4f93-42e7-ace7-ab51399f4808/[0-9a-f]+}
11
- end
11
+ expect(uploaded_file.id).to match %r{\Aasset/81060886-4f93-42e7-ace7-ab51399f4808/[0-9a-f]+}
12
+ end
12
13
 
13
- it "has suffix with a record id and filename" do
14
- uploaded_file = uploader.upload(fakeio(filename: "foo.jpg"), record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
14
+ it "has suffix with a record id and filename" do
15
+ uploaded_file = uploader.upload(fakeio(filename: "foo.jpg"), record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
15
16
 
16
- expect(uploaded_file.id).to match %r{\Aasset/81060886-4f93-42e7-ace7-ab51399f4808/[0-9a-f]+\.jpg}
17
- end
17
+ expect(uploaded_file.id).to match %r{\Aasset/81060886-4f93-42e7-ace7-ab51399f4808/[0-9a-f]+\.jpg}
18
+ end
18
19
 
19
- it "uploads with no record" do
20
- uploaded_file = uploader.upload(fakeio, record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
20
+ it "uploads with no record" do
21
+ uploaded_file = uploader.upload(fakeio, record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
21
22
 
22
- expect(uploaded_file.id).to match %r{\Aasset/[0-9a-f]+}
23
- end
23
+ expect(uploaded_file.id).to match %r{\Aasset/[0-9a-f]+}
24
+ end
24
25
 
25
- it "uploads with record with no id" do
26
- uploaded_file = uploader.upload(fakeio, record: OpenStruct.new(), name: :file)
26
+ it "uploads with record with no id" do
27
+ uploaded_file = uploader.upload(fakeio, record: OpenStruct.new(), name: :file)
27
28
 
28
- expect(uploaded_file.id).to match %r{\Aasset/[0-9a-f]+}
29
+ expect(uploaded_file.id).to match %r{\Aasset/[0-9a-f]+}
30
+ end
29
31
  end
30
32
 
33
+ describe "for shrine derivatives" do
34
+ let(:image_path) { Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg") }
35
+
36
+ let(:uploader) do
37
+ test_uploader do
38
+ plugin :kithe_storage_location
39
+ end
40
+ end
31
41
 
42
+ it "uses good path for derivative" do
43
+ uploaded_file = uploader.upload(fakeio("foo.jpg"), derivative: :fixed, record: OpenStruct.new(id: "81060886-4f93-42e7-ace7-ab51399f4808"), name: :file)
44
+
45
+ expect(uploaded_file.id).to match %r{\A81060886-4f93-42e7-ace7-ab51399f4808/fixed/[0-9a-f]+}
46
+ end
47
+
48
+ it "raises with no record" do
49
+ expect {
50
+ uploader.upload(fakeio("foo.jpg"), record: nil, derivative: :fixed, name: :file)
51
+ }.to raise_error(TypeError)
52
+ end
53
+
54
+ it "raises with record with no id" do
55
+ expect {
56
+ uploader.upload(fakeio("foo.jpg"), record: OpenStruct.new, derivative: :fixed, name: :file)
57
+ }.to raise_error(TypeError)
58
+ end
59
+ end
32
60
  end
@@ -132,13 +132,14 @@ end
132
132
  require 'sane_patch'
133
133
  SanePatch.patch("shrine", "< 3.2.2") do
134
134
  require 'shrine/storage/memory'
135
+
135
136
  class Shrine::Storage::Memory
136
- def open(id, *)
137
- str = store.fetch(id)
138
- StringIO.new(str).set_encoding(str.encoding, str.encoding)
137
+ def open(id, **)
138
+ io = StringIO.new(store.fetch(id))
139
+ io.set_encoding(io.string.encoding) # Ruby 2.7.0 – https://bugs.ruby-lang.org/issues/16497
140
+ io
141
+ rescue KeyError
142
+ raise Shrine::FileNotFound, "file #{id.inspect} not found on storage"
139
143
  end
140
144
  end
141
145
  end
142
-
143
-
144
-
@@ -59,8 +59,9 @@ require "stringio"
59
59
  class FakeIO
60
60
  attr_reader :original_filename, :content_type
61
61
 
62
- def initialize(content, filename: nil, content_type: nil)
62
+ def initialize(content, filename: nil, content_type: nil, encoding: "BINARY")
63
63
  @io = StringIO.new(content)
64
+ @io.set_encoding(encoding, encoding) # weird ruby workaround
64
65
  @original_filename = filename
65
66
  @content_type = content_type
66
67
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kithe
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.alpha2
4
+ version: 2.0.0.pre.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Rochkind
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-18 00:00:00.000000000 Z
11
+ date: 2020-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -272,20 +272,6 @@ dependencies:
272
272
  - - ">="
273
273
  - !ruby/object:Gem::Version
274
274
  version: '0'
275
- - !ruby/object:Gem::Dependency
276
- name: shrine-memory
277
- requirement: !ruby/object:Gem::Requirement
278
- requirements:
279
- - - ">="
280
- - !ruby/object:Gem::Version
281
- version: '0'
282
- type: :development
283
- prerelease: false
284
- version_requirements: !ruby/object:Gem::Requirement
285
- requirements:
286
- - - ">="
287
- - !ruby/object:Gem::Version
288
- version: '0'
289
275
  - !ruby/object:Gem::Dependency
290
276
  name: webmock
291
277
  requirement: !ruby/object:Gem::Requirement
@@ -341,10 +327,9 @@ files:
341
327
  - app/models/kithe/asset.rb
342
328
  - app/models/kithe/asset/derivative_creator.rb
343
329
  - app/models/kithe/asset/derivative_definition.rb
344
- - app/models/kithe/asset/derivative_updater.rb
330
+ - app/models/kithe/asset/set_shrine_uploader.rb
345
331
  - app/models/kithe/collection.rb
346
332
  - app/models/kithe/config_base.rb
347
- - app/models/kithe/derivative.rb
348
333
  - app/models/kithe/mediainfo_analyzer.rb
349
334
  - app/models/kithe/model.rb
350
335
  - app/models/kithe/model_contains.rb
@@ -355,7 +340,6 @@ files:
355
340
  - app/simple_form_enhancements/kithe/form_builder.rb
356
341
  - app/simple_form_enhancements/kithe/repeatable_input_generator.rb
357
342
  - app/uploaders/kithe/asset_uploader.rb
358
- - app/uploaders/kithe/derivative_uploader.rb
359
343
  - app/validators/array_inclusion_validator.rb
360
344
  - config/locales/en.yml
361
345
  - config/routes.rb
@@ -375,7 +359,13 @@ files:
375
359
  - lib/kithe/sti_preload.rb
376
360
  - lib/kithe/version.rb
377
361
  - lib/shrine/plugins/kithe_accept_remote_url.rb
362
+ - lib/shrine/plugins/kithe_checksum_signatures.rb
363
+ - lib/shrine/plugins/kithe_controllable_backgrounding.rb
364
+ - lib/shrine/plugins/kithe_derivative_definitions.rb
365
+ - lib/shrine/plugins/kithe_derivatives.rb
366
+ - lib/shrine/plugins/kithe_determine_mime_type.rb
378
367
  - lib/shrine/plugins/kithe_multi_cache.rb
368
+ - lib/shrine/plugins/kithe_persisted_derivatives.rb
379
369
  - lib/shrine/plugins/kithe_promotion_callbacks.rb
380
370
  - lib/shrine/plugins/kithe_promotion_directives.rb
381
371
  - lib/shrine/plugins/kithe_storage_location.rb
@@ -448,19 +438,23 @@ files:
448
438
  - spec/indexing/indexable_spec.rb
449
439
  - spec/indexing/indexer_spec.rb
450
440
  - spec/indexing/obj_extract_spec.rb
451
- - spec/models/kithe/asset/asset_create_derivatives_spec.rb
441
+ - spec/models/kithe/asset/asset_derivatives_spec.rb
452
442
  - spec/models/kithe/asset/asset_promotion_hooks_spec.rb
443
+ - spec/models/kithe/asset/set_shrine_uploader_spec.rb
453
444
  - spec/models/kithe/asset_spec.rb
454
445
  - spec/models/kithe/collection_spec.rb
455
446
  - spec/models/kithe/config_spec.rb
456
- - spec/models/kithe/derivative_spec.rb
457
447
  - spec/models/kithe/mediainfo_analyzer_spec.rb
458
448
  - spec/models/kithe/model_spec.rb
459
449
  - spec/models/kithe/parameters_spec.rb
460
450
  - spec/models/kithe/representatives_spec.rb
461
451
  - spec/models/kithe/work_spec.rb
462
452
  - spec/rails_helper.rb
453
+ - spec/shrine/kithe_accept_remote_url_spec.rb
454
+ - spec/shrine/kithe_checksum_signatures_spec.rb
455
+ - spec/shrine/kithe_derivative_definitions_spec.rb
463
456
  - spec/shrine/kithe_multi_cache_spec.rb
457
+ - spec/shrine/kithe_persisted_derivatives_spec.rb
464
458
  - spec/shrine/kithe_storage_location_spec.rb
465
459
  - spec/simple_form_enhancements/repeatable_input_generator_spec.rb
466
460
  - spec/spec_helper.rb
@@ -468,6 +462,7 @@ files:
468
462
  - spec/test_support/audio/ice_cubes.mp3
469
463
  - spec/test_support/images/1x1_pixel.jpg
470
464
  - spec/test_support/images/2x2_pixel.jpg
465
+ - spec/test_support/images/3x3_pixel.jpg
471
466
  - spec/test_support/images/photo_800x586.jpg
472
467
  - spec/test_support/shrine_spec_support.rb
473
468
  - spec/test_support/temporary_class_for_specs.rb
@@ -561,23 +556,28 @@ test_files:
561
556
  - spec/derivative_transformers/ffmpeg_transformer_spec.rb
562
557
  - spec/models/kithe/collection_spec.rb
563
558
  - spec/models/kithe/config_spec.rb
559
+ - spec/models/kithe/asset/asset_derivatives_spec.rb
564
560
  - spec/models/kithe/asset/asset_promotion_hooks_spec.rb
565
- - spec/models/kithe/asset/asset_create_derivatives_spec.rb
561
+ - spec/models/kithe/asset/set_shrine_uploader_spec.rb
566
562
  - spec/models/kithe/representatives_spec.rb
567
563
  - spec/models/kithe/work_spec.rb
568
564
  - spec/models/kithe/mediainfo_analyzer_spec.rb
569
565
  - spec/models/kithe/parameters_spec.rb
570
- - spec/models/kithe/derivative_spec.rb
571
566
  - spec/models/kithe/asset_spec.rb
572
567
  - spec/models/kithe/model_spec.rb
573
568
  - spec/shrine/kithe_multi_cache_spec.rb
574
569
  - spec/shrine/kithe_storage_location_spec.rb
570
+ - spec/shrine/kithe_persisted_derivatives_spec.rb
571
+ - spec/shrine/kithe_derivative_definitions_spec.rb
572
+ - spec/shrine/kithe_accept_remote_url_spec.rb
573
+ - spec/shrine/kithe_checksum_signatures_spec.rb
575
574
  - spec/factories/kithe_works.rb
576
575
  - spec/factories/kithe_collections.rb
577
576
  - spec/factories/kithe_assets.rb
578
577
  - spec/test_support/temporary_class_for_specs.rb
579
578
  - spec/test_support/shrine_spec_support.rb
580
579
  - spec/test_support/images/2x2_pixel.jpg
580
+ - spec/test_support/images/3x3_pixel.jpg
581
581
  - spec/test_support/images/1x1_pixel.jpg
582
582
  - spec/test_support/images/photo_800x586.jpg
583
583
  - spec/test_support/audio/README.md
@@ -1,119 +0,0 @@
1
- # A service object to add an IO stream as a derivative with a certain key, to a asset.
2
- # Adds a Derivative database object for such. This class is normally only used from
3
- # Asset#update_derivative, it's a helper object, you aren't expected to use it independently.
4
- #
5
- # This would be very straightforward if it weren't for taking account of a couple concurrency race
6
- # conditions involving data integrity:
7
- #
8
- # 1. There should be only one derivative for a given asset/key pair. This is enforced by
9
- # a DB constraint. If the record already exists, we want to update the current record,
10
- # otherwise add a new one. We want to do this in a race-condition safe way, with possibly
11
- # multiple processes editing db.
12
- #
13
- # 2. The DB should at no point in time contain a derivative generated for an _old_ version
14
- # of the asset. If an asset#file is changed, it's existing derivatives need to be deleted,
15
- # and this needs to happen in a race-condition safe way when something may be trying to
16
- # add a derivative concurrently.
17
- #
18
- # I believe we have solved those challenges, but it leads to a bit tricky code. We use
19
- # a kind of "optimistic" approach to (1) (try to insert, if you get a uniqueness violation
20
- # try to find and use the record that's already there). And a "pessimistic" approach to (2),
21
- # where we actually briefly take out a DB pessimistic lock to make sure the asset#file hasn't
22
- # changed, and can't until we're done updating. (using sha512 as a marker, which is why you
23
- # can't add an asset until it has a sha512 in it's metadata, usually post-promotion).
24
- #
25
- # If we made a given Asset objects's file bytestream immutable, this would all be a lot simpler;
26
- # we wouldn't need to worry about (2) at all, and maybe not even (1). We might consider that, but
27
- # for now we're tackling the hard way.
28
- #
29
- class Kithe::Asset::DerivativeUpdater
30
- attr_reader :asset, :key, :io, :storage_key, :metadata, :max_optimistic_tries
31
-
32
- def initialize(asset, key, io, storage_key: :kithe_derivatives, metadata: {})
33
- @asset = asset
34
- @key = key
35
- @io = io
36
- @storage_key = storage_key
37
- @metadata = metadata
38
-
39
- @max_optimistic_tries = 3
40
-
41
- unless asset_has_persisted_sha512?
42
- raise ArgumentError.new("Can not safely add derivative to an asset without a persisted sha512 value")
43
- end
44
- end
45
-
46
- def update
47
- deriv = Kithe::Derivative.new(key: key.to_s, asset: asset)
48
-
49
- # skip cache phase, right to specified storage, but with metadata extraction.
50
- uploader = deriv.file_attacher.shrine_class.new(storage_key)
51
-
52
- # add our derivative key to context when uploading, so Kithe::DerivativeUploader can
53
- # use it if needed.
54
- uploaded_file = uploader.upload(io, record: deriv, metadata: metadata, kithe_derivative_key: key)
55
- optimistically_save_derivative(uploaded_file: uploaded_file, derivative: deriv)
56
- end
57
-
58
- # Attaches UploadedFile to Derivative and tries to save it -- if we get a
59
- # unique constraint violation because a Derivative for that asset/key already existed,
60
- # we fetch that alredy existing one from the db and update it's actual bytestream.
61
- #
62
- # This method calls itself recursively to do that. Gives up after max_optimistic_tries,
63
- # at which point it'll just raise the constraint violation exception.
64
- def optimistically_save_derivative(uploaded_file:, derivative:, tries: 0)
65
- derivative.file_attacher.change(uploaded_file)
66
- save_deriv_ensuring_unchanged_asset(derivative)
67
- rescue ActiveRecord::RecordNotUnique => e
68
- if tries < max_optimistic_tries
69
- # find the one that's already there, try to attach our new file
70
- # to that one
71
- derivative = Kithe::Derivative.where(key: key.to_s, asset: asset).first || derivative
72
- optimistically_save_derivative(uploaded_file: uploaded_file, derivative: derivative, tries: tries + 1)
73
- else
74
- uploaded_file.delete if uploaded_file
75
- raise e
76
- end
77
- rescue StandardError => e
78
- # aggressively clean up our file on errors!
79
- uploaded_file.delete if uploaded_file
80
- raise e
81
- end
82
-
83
- # Save a Derivative model with some fancy DB footwork to ensure at the time
84
- # we save it, the original asset file it is based on is still in db unchanged,
85
- # in a concurrency-safe way.
86
- #
87
- # We re-fetch to ensure asset still exists, with sha512 we expect. (kithe model ensures sha512
88
- # exists in shrine metadata). With a pessmistic lock in a transaction. This ensures that at
89
- # the point we save the new derivative, the db is still in a state where the original file
90
- # the derivative relates to is still in the db.
91
- #
92
- # Can raise a ActiveRecord::RecordNotUnique, if derivative unique constraint is violated,
93
- # that is handled above here.
94
- def save_deriv_ensuring_unchanged_asset(deriv)
95
- # fancy throw/catch keep our abort rescue from being in the transaction
96
- catch(:kithe_unchanged_abort) do
97
- Kithe::Asset.transaction do
98
- # the file we're trying to add a derivative to doesn't exist anymore, forget it
99
- unless asset.acquire_lock_on_sha
100
- throw :kithe_unchanged_abort
101
- end
102
-
103
- deriv.save!
104
- return deriv
105
- end
106
- end
107
-
108
- # If we made it here, we've aborted
109
- deriv.file.delete
110
- return nil
111
- end
112
-
113
- def asset_has_persisted_sha512?
114
- asset.persisted? && asset.sha512.present? &&
115
- !( asset.file_data_changed? &&
116
- asset.file_data_change.first.try(:dig, "metadata", "sha512") !=
117
- asset.file_data_change.second.try(:dig, "metadata", "sha512"))
118
- end
119
- end
@@ -1,15 +0,0 @@
1
- module Kithe
2
-
3
- # Derivatives by default will be stored in Shrine storage :kithe_derivatives, so
4
- # that should be registered in your app.
5
- #
6
- # Only one deriv can exist for a given asset_id/key pair, enforced by db constraint.
7
- class Derivative < ApplicationRecord
8
- # the fk is to kithe_models STI table, but we only intend for assets
9
- belongs_to :asset, class_name: "Kithe::Asset"
10
-
11
- include Kithe::DerivativeUploader::Attachment.new(:file, store: :kithe_derivatives)
12
-
13
- delegate :content_type, :size, :height, :width, :url, to: :file, allow_nil: true
14
- end
15
- end
@@ -1,48 +0,0 @@
1
- require 'mini_mime'
2
-
3
- module Kithe
4
- # The derivative uploader doesn't have to do too much, we don't even use
5
- # promotion for derivatives, just writing directly to a storage.
6
- #
7
- # But it needs activerecord integration, and limited metadata automatic extraction.
8
- class DerivativeUploader < Shrine
9
- plugin :activerecord
10
-
11
- plugin :determine_mime_type, analyzer: :marcel
12
-
13
- # ignore error, often from storing a non-image file which can't have dimensions
14
- # extracted. behavior consistent with shrine 2.x.
15
- plugin :store_dimensions, on_error: :ignore
16
-
17
- # Useful in case consumers want it, and doesn't harm anything to be available.
18
- # https://github.com/shrinerb/shrine/blob/master/doc/plugins/rack_response.md
19
- plugin :rack_response
20
-
21
- # should this be in a plugin? location in file system based on original asset
22
- # id and derivative key, as well as unique random file id from shrine.
23
- def generate_location(io, context)
24
- # assumes we're only used with Derivative model, that has an asset_id and key
25
- asset_id = context[:record].asset_id
26
- key = context[:record].key
27
- original = super
28
- [asset_id, key, original].compact.join("/")
29
- end
30
-
31
-
32
- # Override to fix "filename" metadata to be something reasonable, regardless
33
- # of what if anything was the filename of the IO being attached. shrine S3 will
34
- # insist on setting a default content-disposition with this filename.
35
- def extract_metadata(io, context = {})
36
- result = super
37
-
38
- if context[:kithe_derivative_key] &&
39
- context[:record]
40
- extension = MiniMime.lookup_by_content_type(result["mime_type"] || "")&.extension
41
- result["filename"] = "#{context[:record].asset.friendlier_id}_#{context[:kithe_derivative_key]}.#{extension}"
42
- result["kithe_derivative_key"] = context[:kithe_derivative_key]
43
- end
44
-
45
- return result
46
- end
47
- end
48
- end
@@ -1,320 +0,0 @@
1
- # Make a new test file cause it's a buncha func
2
- require 'rails_helper'
3
-
4
- # Not sure how to get our
5
- describe "Kithe::Asset derivative definitions", queue_adapter: :test do
6
- let(:a_jpg_deriv_file) { Kithe::Engine.root.join("spec/test_support/images/2x2_pixel.jpg") }
7
-
8
- temporary_class("TestAssetSubclass") do
9
- deriv_src_path = a_jpg_deriv_file
10
- Class.new(Kithe::Asset) do
11
- define_derivative(:some_data) do |original_file|
12
- StringIO.new("some one data")
13
- end
14
-
15
- define_derivative(:a_jpg) do |original_file|
16
- FileUtils.cp(deriv_src_path,
17
- Kithe::Engine.root.join("spec/test_support/images/2x2_pixel-TEMP.jpg"))
18
-
19
- File.open(Kithe::Engine.root.join("spec/test_support/images/2x2_pixel-TEMP.jpg"))
20
- end
21
- end
22
- end
23
-
24
- let(:asset) do
25
- TestAssetSubclass.create(title: "test",
26
- file: File.open(Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg"))
27
- ).tap do |a|
28
- # We want to promote without create_derivatives being automatically called
29
- # as usual, so we can test create_derivatives manually.
30
- a.file_attacher.set_promotion_directives(create_derivatives: false)
31
- a.promote
32
-
33
- # Precondition assumptions for our test setup to be valid
34
- expect(a.file_attacher.stored?).to be(true)
35
- expect(a.derivatives).to be_empty
36
- end
37
- end
38
-
39
- it "builds derivatives" do
40
- asset.create_derivatives
41
-
42
- one_deriv = asset.derivatives.find { |d| d.key == "some_data" }
43
- expect(one_deriv).to be_present
44
- expect(one_deriv.file.read).to eq("some one data")
45
-
46
- jpg_deriv = asset.derivatives.find {|d| d.key == "a_jpg"}
47
- expect(jpg_deriv.file.read).to eq(File.read(a_jpg_deriv_file, encoding: "BINARY"))
48
- end
49
-
50
- it "sets #derivatives_created?" do
51
- expect(asset.derivatives_created?).to be(false)
52
- asset.create_derivatives
53
- asset.reload
54
- expect(asset.derivatives_created?).to be(true)
55
- end
56
-
57
-
58
- describe "Original deleted before derivatives can be created", queue_adapter: :inline do
59
- let(:short_lived_asset) do
60
- TestAssetSubclass.create!(title: "test",
61
- file: File.open(Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg")))
62
- end
63
- it """catches the ActiveJob::DeserializationError
64
- if the asset is no longer in the database
65
- once the derivative creation job starts up.""" do
66
- id_to_delete = short_lived_asset.id
67
- Kithe::Derivative.where(asset_id: id_to_delete).delete_all
68
- Kithe::Model.where(id: id_to_delete).delete_all
69
-
70
- # short_lived_asset is no longer in the DB.
71
- # Let's try and create derivatives for it:
72
- expect do
73
- Kithe::CreateDerivativesJob.perform_later(short_lived_asset)
74
- end.not_to raise_error
75
- end
76
- end
77
-
78
- describe "under normal operation", queue_adapter: :inline do
79
- let(:asset) do
80
- TestAssetSubclass.create!(title: "test",
81
- file: File.open(Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg")))
82
- end
83
- it "automatically creates derivatives" do
84
- expect(asset.derivatives.count).to eq(2)
85
- end
86
- end
87
-
88
- it "extracts limited metadata from derivative" do
89
- asset.create_derivatives
90
-
91
- jpg_deriv = asset.derivatives.find {|d| d.key == "a_jpg"}
92
- expect(jpg_deriv.size).to eq(File.size(Kithe::Engine.root.join("spec/test_support/images/2x2_pixel.jpg")))
93
- expect(jpg_deriv.width).to eq(2)
94
- expect(jpg_deriv.height).to eq(2)
95
- expect(jpg_deriv.content_type).to eq("image/jpeg")
96
- end
97
-
98
- it "deletes derivative file returned by block" do
99
- asset.create_derivatives
100
-
101
- expect(File.exist?(Kithe::Engine.root.join("spec/test_support/images/2x2_pixel-TEMP.jpg"))).not_to be(true)
102
- end
103
-
104
- it "by default saves in :kithe_derivatives storage" do
105
- asset.create_derivatives
106
-
107
- jpg_deriv = asset.derivatives.find {|d| d.key == "a_jpg"}
108
- expect(jpg_deriv.file.storage_key).to eq(:kithe_derivatives)
109
- end
110
-
111
-
112
- describe "block arguments" do
113
- let(:monitoring_proc) do
114
- proc do |original_file, record:|
115
- expect(original_file.kind_of?(File) || original_file.kind_of?(Tempfile)).to be(true)
116
- expect(original_file.path).to be_present
117
- expect(original_file.read).to eq(asset.file.read)
118
-
119
- expect(record).to eq(asset)
120
-
121
- nil
122
- end
123
- end
124
-
125
- temporary_class("TestAssetSubclass") do
126
- our_proc = monitoring_proc
127
- Class.new(Kithe::Asset) do
128
- define_derivative(:some_data, &our_proc)
129
- end
130
- end
131
-
132
- it "as expected" do
133
- expect(monitoring_proc).to receive(:call).and_call_original
134
-
135
- asset.create_derivatives
136
- expect(asset.derivatives.length).to eq(0)
137
- end
138
- end
139
-
140
- describe "custom storage_key" do
141
- temporary_class("TestAssetSubclass") do
142
- Class.new(Kithe::Asset) do
143
- define_derivative(:some_data, storage_key: :store) do |original_file|
144
- StringIO.new("some one data")
145
- end
146
- end
147
- end
148
- it "saves appropriately" do
149
- asset.create_derivatives
150
-
151
- deriv = asset.derivatives.first
152
-
153
- expect(deriv).to be_present
154
- expect(deriv.file.storage_key).to eq(:store)
155
- end
156
- end
157
-
158
- describe "default_create false" do
159
- let(:monitoring_proc) { proc { |asset| } }
160
-
161
- temporary_class("TestAssetSubclass") do
162
- p = monitoring_proc
163
- Class.new(Kithe::Asset) do
164
- define_derivative(:some_data, default_create: false, &p)
165
- end
166
- end
167
-
168
- it "is not run automatically" do
169
- expect(monitoring_proc).not_to receive(:call)
170
- asset.create_derivatives
171
- end
172
- end
173
-
174
- describe "only/except" do
175
- let(:monitoring_proc1) { proc { |asset| StringIO.new("one") } }
176
- let(:monitoring_proc2) { proc { |asset| StringIO.new("two") } }
177
- let(:monitoring_proc3) { proc { |asset| StringIO.new("three") } }
178
-
179
- temporary_class("TestAssetSubclass") do
180
- p1, p2, p3 = monitoring_proc1, monitoring_proc2, monitoring_proc3
181
- Class.new(Kithe::Asset) do
182
- define_derivative(:one, default_create: false, &p1)
183
- define_derivative(:two, &p2)
184
- define_derivative(:three, &p3)
185
- end
186
- end
187
-
188
- it "can call with only" do
189
- expect(monitoring_proc1).to receive(:call).and_call_original
190
- expect(monitoring_proc2).to receive(:call).and_call_original
191
- expect(monitoring_proc3).not_to receive(:call)
192
-
193
- asset.create_derivatives(only: [:one, :two])
194
-
195
- expect(asset.derivatives.collect(&:key)).to eq(["one", "two"])
196
- end
197
-
198
- it "can call with except" do
199
- expect(monitoring_proc1).not_to receive(:call)
200
- expect(monitoring_proc2).to receive(:call).and_call_original
201
- expect(monitoring_proc3).not_to receive(:call)
202
-
203
- asset.create_derivatives(except: [:three])
204
-
205
- expect(asset.derivatives.collect(&:key)).to eq(["two"])
206
- end
207
-
208
- it "can call with only and except" do
209
- expect(monitoring_proc1).to receive(:call).and_call_original
210
- expect(monitoring_proc2).not_to receive(:call)
211
- expect(monitoring_proc3).not_to receive(:call)
212
-
213
- asset.create_derivatives(only: [:one, :two], except: :two)
214
-
215
- expect(asset.derivatives.collect(&:key)).to eq(["one"])
216
- end
217
- end
218
-
219
- describe "content_type filters" do
220
- temporary_class("TestAssetSubclass") do
221
- Class.new(Kithe::Asset) do
222
- define_derivative(:never_called, content_type: "nothing/nothing") { |o| StringIO.new("never") }
223
- define_derivative(:gated_positive, content_type: "image/jpeg") { |o| StringIO.new("gated positive") }
224
- define_derivative(:gated_positive_main_type, content_type: "image") { |o| StringIO.new("gated positive") }
225
- end
226
- end
227
-
228
- it "does not call if content type does not match" do
229
- asset.create_derivatives
230
- expect(asset.derivatives.collect(&:key)).not_to include("never_called")
231
- end
232
-
233
- it "calls for exact content type match" do
234
- asset.create_derivatives
235
- expect(asset.derivatives.collect(&:key)).to include("gated_positive")
236
- end
237
-
238
- it "calls for main content type match" do
239
- asset.create_derivatives
240
- expect(asset.derivatives.collect(&:key)).to include("gated_positive_main_type")
241
- end
242
-
243
- describe "as array" do
244
- temporary_class("TestAssetSubclass") do
245
- Class.new(Kithe::Asset) do
246
- define_derivative(:never_called, content_type: ["nothing/nothing", "also/nothing"]) { |o| StringIO.new("never") }
247
- define_derivative(:gated_positive, content_type: ["image/jpeg", "something/else"]) { |o| StringIO.new("gated positive") }
248
- end
249
- end
250
- it "calls for one match" do
251
- asset.create_derivatives
252
- expect(asset.derivatives.collect(&:key)).to eq(["gated_positive"])
253
- end
254
- end
255
-
256
- describe "conflicting types" do
257
- let(:unfiltered) { proc { |asset| StringIO.new("unfiltered") } }
258
- let(:image) { proc { |asset| StringIO.new("image") } }
259
- let(:image_jpeg) { proc { |asset| StringIO.new("image/jpeg") } }
260
-
261
-
262
- temporary_class("TestAssetSubclass") do
263
- u, i, ij = unfiltered, image, image_jpeg
264
- Class.new(Kithe::Asset) do
265
- define_derivative(:key, &u)
266
- define_derivative(:key, content_type: "image/jpeg", &ij)
267
- define_derivative(:key, content_type: "image", &i)
268
- end
269
- end
270
-
271
- it "takes most specific" do
272
- expect(unfiltered).not_to receive(:call)
273
- expect(image).not_to receive(:call)
274
- expect(image_jpeg).to receive(:call).and_call_original
275
-
276
- asset.create_derivatives
277
- expect(asset.derivatives.count).to eq(1)
278
-
279
- deriv = asset.derivatives.first
280
- expect(deriv.key).to eq("key")
281
- expect(deriv.file.read). to eq("image/jpeg")
282
- end
283
- end
284
- end
285
-
286
- describe "lazy creation" do
287
- before do
288
- asset.class.derivative_definitions.collect(&:key).each do |key|
289
- asset.update_derivative(key, StringIO.new("#{key} original"))
290
- end
291
- end
292
-
293
- it "does not re-create" do
294
- derivatives_pre_creation = asset.derivatives.collect(&:attributes)
295
-
296
- asset.create_derivatives(lazy: true)
297
- derivatives_post_creation = asset.derivatives.reload.collect(&:attributes)
298
-
299
- expect(derivatives_post_creation).to eq(derivatives_pre_creation)
300
- end
301
- end
302
-
303
- describe "#remove_derivative_definition!" do
304
- it "can remove by string" do
305
- original_keys = TestAssetSubclass.defined_derivative_keys
306
- TestAssetSubclass.remove_derivative_definition!(original_keys.first.to_s)
307
- expect(TestAssetSubclass.defined_derivative_keys).to eq(original_keys.slice(1..original_keys.length))
308
- end
309
- it "can remove by symbol" do
310
- original_keys = TestAssetSubclass.defined_derivative_keys
311
- TestAssetSubclass.remove_derivative_definition!(original_keys.first.to_sym)
312
- expect(TestAssetSubclass.defined_derivative_keys).to eq(original_keys.slice(1..original_keys.length))
313
- end
314
- it "can remove multiple args" do
315
- original_keys = TestAssetSubclass.defined_derivative_keys
316
- TestAssetSubclass.remove_derivative_definition!(*original_keys)
317
- expect(TestAssetSubclass.defined_derivative_keys).to eq([])
318
- end
319
- end
320
- end