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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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