kithe 1.1.2 → 2.0.0.pre.alpha1
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/app/jobs/kithe/asset_delete_job.rb +5 -2
- data/app/jobs/kithe/asset_promote_job.rb +12 -2
- data/app/models/kithe/asset.rb +14 -6
- data/app/models/kithe/asset/derivative_updater.rb +2 -3
- data/app/uploaders/kithe/asset_uploader.rb +24 -21
- data/app/uploaders/kithe/derivative_uploader.rb +7 -3
- data/lib/kithe/version.rb +1 -1
- data/lib/shrine/plugins/kithe_accept_remote_url.rb +36 -9
- data/lib/shrine/plugins/kithe_multi_cache.rb +3 -6
- data/lib/shrine/plugins/kithe_promotion_callbacks.rb +82 -0
- data/lib/shrine/plugins/kithe_promotion_directives.rb +111 -0
- data/spec/dummy/log/development.log +1 -0
- data/spec/dummy/log/test.log +51669 -0
- data/spec/models/kithe/asset/asset_create_derivatives_spec.rb +7 -3
- data/spec/models/kithe/asset/asset_promotion_hooks_spec.rb +179 -12
- data/spec/models/kithe/asset_spec.rb +3 -2
- data/spec/models/kithe/derivative_spec.rb +4 -4
- data/spec/shrine/kithe_multi_cache_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/test_support/shrine_spec_support.rb +2 -1
- metadata +9 -8
- data/lib/shrine/plugins/kithe_promotion_hooks.rb +0 -138
@@ -27,8 +27,12 @@ describe "Kithe::Asset derivative definitions", queue_adapter: :test do
|
|
27
27
|
).tap do |a|
|
28
28
|
# We want to promote without create_derivatives being automatically called
|
29
29
|
# as usual, so we can test create_derivatives manually.
|
30
|
-
a.file_attacher.set_promotion_directives(
|
30
|
+
a.file_attacher.set_promotion_directives(create_derivatives: false)
|
31
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
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -101,7 +105,7 @@ describe "Kithe::Asset derivative definitions", queue_adapter: :test do
|
|
101
105
|
asset.create_derivatives
|
102
106
|
|
103
107
|
jpg_deriv = asset.derivatives.find {|d| d.key == "a_jpg"}
|
104
|
-
expect(jpg_deriv.file.storage_key).to eq(
|
108
|
+
expect(jpg_deriv.file.storage_key).to eq(:kithe_derivatives)
|
105
109
|
end
|
106
110
|
|
107
111
|
|
@@ -147,7 +151,7 @@ describe "Kithe::Asset derivative definitions", queue_adapter: :test do
|
|
147
151
|
deriv = asset.derivatives.first
|
148
152
|
|
149
153
|
expect(deriv).to be_present
|
150
|
-
expect(deriv.file.storage_key).to eq(
|
154
|
+
expect(deriv.file.storage_key).to eq(:store)
|
151
155
|
end
|
152
156
|
end
|
153
157
|
|
@@ -15,6 +15,28 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
|
|
15
15
|
)
|
16
16
|
}
|
17
17
|
|
18
|
+
describe "before_promotion" do
|
19
|
+
temporary_class("TestAsset") do
|
20
|
+
Class.new(Kithe::Asset) do
|
21
|
+
before_promotion do
|
22
|
+
$metadata_in_before_promotion = self.file.metadata
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
before do
|
27
|
+
$metadata_in_before_promotion = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# we have a built-in before_promotion for metadata extraction,
|
31
|
+
# make sure it happens before any additional before_promotions,
|
32
|
+
# so they can eg use it to cancel
|
33
|
+
it "has access to automatic metadata extraction" do
|
34
|
+
unsaved_asset.save!
|
35
|
+
expect($metadata_in_before_promotion).to be_present
|
36
|
+
expect($metadata_in_before_promotion['sha512']).to be_present
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
18
40
|
describe "before_promotion cancellation" do
|
19
41
|
temporary_class("TestAsset") do
|
20
42
|
Class.new(Kithe::Asset) do
|
@@ -28,23 +50,138 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
|
|
28
50
|
end
|
29
51
|
end
|
30
52
|
|
31
|
-
|
32
|
-
|
53
|
+
describe "with inline promotion", queue_adapter: :test do
|
54
|
+
before do
|
55
|
+
unsaved_asset.file_attacher.set_promotion_directives(promote: :inline)
|
56
|
+
end
|
33
57
|
|
34
|
-
|
35
|
-
|
36
|
-
|
58
|
+
it "cancels" do
|
59
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:promote)
|
60
|
+
|
61
|
+
unsaved_asset.save!
|
62
|
+
unsaved_asset.reload
|
63
|
+
expect(unsaved_asset.reload.stored?).to be(false)
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "with promotion_directives[:skip_callbacks]" do
|
67
|
+
it "doesn't cancel" do
|
68
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).to receive(:promote).and_call_original
|
69
|
+
|
70
|
+
unsaved_asset.file_attacher.set_promotion_directives(skip_callbacks: true)
|
71
|
+
unsaved_asset.save!
|
72
|
+
unsaved_asset.reload
|
73
|
+
|
74
|
+
expect(unsaved_asset.stored?).to be(true)
|
75
|
+
end
|
76
|
+
end
|
37
77
|
end
|
38
78
|
|
39
|
-
describe "with
|
40
|
-
it "
|
41
|
-
expect_any_instance_of(Kithe::AssetUploader::Attacher).
|
79
|
+
describe "with backgrounding promotion", queue_adapter: :inline do
|
80
|
+
it "cancels" do
|
81
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:promote)
|
42
82
|
|
43
|
-
unsaved_asset.file_attacher.set_promotion_directives(skip_callbacks: true)
|
44
83
|
unsaved_asset.save!
|
45
84
|
unsaved_asset.reload
|
85
|
+
expect(unsaved_asset.stored?).to be(false)
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "with promotion_directives[:skip_callbacks]" do
|
89
|
+
it "doesn't cancel" do
|
90
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).to receive(:promote).and_call_original
|
91
|
+
|
92
|
+
unsaved_asset.file_attacher.set_promotion_directives(skip_callbacks: true)
|
93
|
+
unsaved_asset.save!
|
94
|
+
unsaved_asset.reload
|
95
|
+
|
96
|
+
expect(unsaved_asset.stored?).to be(true)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
describe "assigning directly to store" do
|
103
|
+
temporary_class("TestAsset") do
|
104
|
+
Class.new(Kithe::Asset) do
|
105
|
+
before_promotion do
|
106
|
+
raise "Should not call before_promotion"
|
107
|
+
end
|
108
|
+
|
109
|
+
after_promotion do
|
110
|
+
raise "Should not call after_promotion"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
let(:asset) {
|
116
|
+
TestAsset.create(title: "test")
|
117
|
+
}
|
118
|
+
|
119
|
+
let(:filepath) { Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg") }
|
120
|
+
|
121
|
+
describe "with inline promoting" do
|
122
|
+
before do
|
123
|
+
asset.file_attacher.set_promotion_directives(promote: :inline)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should not call callbacks" do
|
127
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:promote)
|
128
|
+
|
129
|
+
asset.file_attacher.attach(File.open(filepath))
|
130
|
+
asset.save!
|
131
|
+
|
132
|
+
expect(asset.changed?).to be(false)
|
133
|
+
asset.reload
|
134
|
+
expect(asset.file).to be_present
|
135
|
+
expect(asset.stored?).to be(true)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "with background promoting", queue_adapter: :inline do
|
140
|
+
before do
|
141
|
+
asset.file_attacher.set_promotion_directives(promote: :background)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should not call callbacks" do
|
145
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:promote)
|
146
|
+
|
147
|
+
asset.file_attacher.attach(File.open(filepath))
|
148
|
+
asset.save!
|
149
|
+
|
150
|
+
expect(asset.changed?).to be(false)
|
151
|
+
asset.reload
|
152
|
+
expect(asset.file).to be_present
|
153
|
+
expect(asset.stored?).to be(true)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
describe "calling Asset#promote directly", queue_adapter: :inline do
|
160
|
+
before do
|
161
|
+
unsaved_asset.file_attacher.set_promotion_directives(promote: false)
|
162
|
+
unsaved_asset.save!
|
163
|
+
# precondition
|
164
|
+
expect(unsaved_asset.reload.file_attacher.cached?).to be(true)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "cancels" do
|
168
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:promote)
|
169
|
+
|
170
|
+
unsaved_asset.promote
|
171
|
+
unsaved_asset.reload
|
172
|
+
expect(unsaved_asset.stored?).to be(false)
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "with promotion_directives[:skip_callbacks]" do
|
176
|
+
it "doesn't cancel" do
|
177
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).to receive(:promote).and_call_original
|
46
178
|
|
47
|
-
|
179
|
+
unsaved_asset.file_attacher.set_promotion_directives(skip_callbacks: true)
|
180
|
+
unsaved_asset.promote
|
181
|
+
unsaved_asset.reload
|
182
|
+
|
183
|
+
expect(unsaved_asset.stored?).to be(true)
|
184
|
+
end
|
48
185
|
end
|
49
186
|
end
|
50
187
|
end
|
@@ -56,7 +193,7 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
|
|
56
193
|
receiver = after_promotion_receiver
|
57
194
|
Class.new(Kithe::Asset) do
|
58
195
|
after_promotion do
|
59
|
-
receiver.call
|
196
|
+
receiver.call(self)
|
60
197
|
end
|
61
198
|
end
|
62
199
|
end
|
@@ -66,6 +203,29 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
|
|
66
203
|
unsaved_asset.save!
|
67
204
|
end
|
68
205
|
|
206
|
+
describe "with inline promotion" do
|
207
|
+
before do
|
208
|
+
unsaved_asset.file_attacher.set_promotion_directives(promote: :inline)
|
209
|
+
end
|
210
|
+
|
211
|
+
# this is actually what's checking for following example...
|
212
|
+
let(:after_promotion_receiver) do
|
213
|
+
proc do |asset|
|
214
|
+
expect(asset.changed?).to be(false)
|
215
|
+
|
216
|
+
asset.reload
|
217
|
+
|
218
|
+
expect(asset.stored?).to be(true)
|
219
|
+
expect(asset.sha512).to be_present
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
it "asset has metadata and is finalized" do
|
224
|
+
expect(after_promotion_receiver).to receive(:call).and_call_original
|
225
|
+
unsaved_asset.save!
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
69
229
|
describe "with promotion_directives[:skip_callbacks]" do
|
70
230
|
it "doesn't call" do
|
71
231
|
expect(after_promotion_receiver).not_to receive(:call)
|
@@ -178,7 +338,7 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
|
|
178
338
|
let!(:existing_file) { saved_asset.file }
|
179
339
|
|
180
340
|
it "can cancel deletion" do
|
181
|
-
|
341
|
+
expect_any_instance_of(Kithe::AssetUploader::Attacher).not_to receive(:destroy)
|
182
342
|
|
183
343
|
|
184
344
|
saved_asset.set_promotion_directives(delete: false)
|
@@ -224,5 +384,12 @@ describe "Kithe::Asset promotion hooks", queue_adapter: :inline do
|
|
224
384
|
asset.set_promotion_directives(promote: :inline)
|
225
385
|
expect(asset.file_attacher.promotion_directives).to eq("promote" => "inline")
|
226
386
|
end
|
387
|
+
|
388
|
+
it "setting from instance writer is aggregative" do
|
389
|
+
Kithe::Asset.promotion_directives = { promote: :inline }
|
390
|
+
asset = Kithe::Asset.new
|
391
|
+
asset.set_promotion_directives(create_derivatives: false)
|
392
|
+
expect(asset.file_attacher.promotion_directives).to eq("promote" => "inline", "create_derivatives" => "false")
|
393
|
+
end
|
227
394
|
end
|
228
395
|
end
|
@@ -107,7 +107,7 @@ RSpec.describe Kithe::Asset, type: :model do
|
|
107
107
|
asset.save!
|
108
108
|
asset.reload
|
109
109
|
|
110
|
-
expect(asset.file.storage_key).to eq(asset.file_attacher.store.storage_key.
|
110
|
+
expect(asset.file.storage_key).to eq(asset.file_attacher.store.storage_key.to_sym)
|
111
111
|
expect(asset.stored?).to be true
|
112
112
|
expect(asset.file.read).to include("Example Response")
|
113
113
|
expect(asset.file.id).to end_with(".html") # no query params
|
@@ -120,6 +120,7 @@ RSpec.describe Kithe::Asset, type: :model do
|
|
120
120
|
asset.file = {"id" => "http://www.example.com/bar.html?foo=bar",
|
121
121
|
"storage" => "remote_url",
|
122
122
|
"headers" => {"Authorization" => "Bearer TestToken"}}
|
123
|
+
|
123
124
|
asset.save!
|
124
125
|
|
125
126
|
expect(
|
@@ -172,7 +173,7 @@ RSpec.describe Kithe::Asset, type: :model do
|
|
172
173
|
file: File.open(Kithe::Engine.root.join("spec/test_support/images/1x1_pixel.jpg"))
|
173
174
|
).tap do |a|
|
174
175
|
a.file_attacher.set_promotion_directives(skip_callbacks: true)
|
175
|
-
a.promote
|
176
|
+
#a.promote
|
176
177
|
a.reload
|
177
178
|
a.update_derivative(:existing, StringIO.new("content"))
|
178
179
|
end
|
@@ -52,7 +52,7 @@ RSpec.describe Kithe::Derivative, type: :model, queue_adapter: :test do
|
|
52
52
|
# file is stored
|
53
53
|
expect(derivative.key).to eq(key)
|
54
54
|
expect(derivative.file).to be_present
|
55
|
-
expect(derivative.file.storage_key).to eq(
|
55
|
+
expect(derivative.file.storage_key).to eq(:kithe_derivatives)
|
56
56
|
expect(derivative.file.read).to eq(dummy_content)
|
57
57
|
|
58
58
|
# some metadata we got
|
@@ -63,7 +63,7 @@ RSpec.describe Kithe::Derivative, type: :model, queue_adapter: :test do
|
|
63
63
|
expect(derivative.file.metadata["filename"]).to eq("#{asset.friendlier_id}_some_derivative.jpeg")
|
64
64
|
|
65
65
|
# path on storage is nice and pretty
|
66
|
-
expect(derivative.file.id).to match %r{\A#{asset.id}/#{key}/[a-f0-9]+\.
|
66
|
+
expect(derivative.file.id).to match %r{\A#{asset.id}/#{key}/[a-f0-9]+\.jpeg\Z}
|
67
67
|
end
|
68
68
|
|
69
69
|
it "can add a derivative with custom storage location" do
|
@@ -72,11 +72,11 @@ RSpec.describe Kithe::Derivative, type: :model, queue_adapter: :test do
|
|
72
72
|
expect(derivative).to be_present
|
73
73
|
derivative.reload
|
74
74
|
expect(derivative.file).to be_present
|
75
|
-
expect(derivative.file.storage_key).to eq(
|
75
|
+
expect(derivative.file.storage_key).to eq(:store)
|
76
76
|
end
|
77
77
|
|
78
78
|
it "can add a derivative with custom metadata" do
|
79
|
-
derivative = asset.update_derivative(key, dummy_io, metadata: { foo
|
79
|
+
derivative = asset.update_derivative(key, dummy_io, metadata: { "foo" => "bar" })
|
80
80
|
expect(derivative).to be_present
|
81
81
|
expect(derivative.file.metadata["size"]).to eq(dummy_content.length)
|
82
82
|
expect(derivative.file.metadata["foo"]).to eq("bar")
|
@@ -22,7 +22,7 @@ describe Shrine::Plugins::KitheMultiCache do
|
|
22
22
|
it "can promote from additional cache" do
|
23
23
|
extra_storage.upload(fakeio("test_content"), "test_id")
|
24
24
|
attacher.assign({"id" => "test_id", "storage" => "additional_one"}.to_json)
|
25
|
-
attacher.promote
|
25
|
+
attacher.promote
|
26
26
|
|
27
27
|
uploaded_file = attacher.get
|
28
28
|
expect(uploaded_file).not_to be_nil
|
data/spec/spec_helper.rb
CHANGED
@@ -130,7 +130,7 @@ end
|
|
130
130
|
# https://github.com/shrinerb/shrine/pull/443
|
131
131
|
#
|
132
132
|
require 'sane_patch'
|
133
|
-
SanePatch.patch("shrine", "< 3") do
|
133
|
+
SanePatch.patch("shrine", "< 3.2.2") do
|
134
134
|
require 'shrine/storage/memory'
|
135
135
|
class Shrine::Storage::Memory
|
136
136
|
def open(id, *)
|
@@ -3,6 +3,7 @@ module ShrineSpecSupport
|
|
3
3
|
# https://github.com/shrinerb/shrine/blob/203c2c9a0c83815c9ded1b09d5d006b2a523579c/test/support/generic_helper.rb#L6
|
4
4
|
def test_uploader(storage_key = :store, &block)
|
5
5
|
uploader_class = Class.new(Shrine)
|
6
|
+
uploader_class.plugin :model
|
6
7
|
uploader_class.storages[:cache] = Shrine::Storage::Test.new
|
7
8
|
uploader_class.storages[:store] = Shrine::Storage::Test.new
|
8
9
|
uploader_class.class_eval(&block) if block
|
@@ -13,7 +14,7 @@ module ShrineSpecSupport
|
|
13
14
|
uploader = test_uploader(*args, &block)
|
14
15
|
Object.send(:remove_const, "TestUser") if defined?(TestUser) # for warnings
|
15
16
|
user_class = Object.const_set("TestUser", Struct.new(:avatar_data, :id))
|
16
|
-
user_class.include uploader.class::Attachment
|
17
|
+
user_class.include uploader.class::Attachment(:avatar, **attachment_options)
|
17
18
|
user_class.new.avatar_attacher
|
18
19
|
end
|
19
20
|
|
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:
|
4
|
+
version: 2.0.0.pre.alpha1
|
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-04-
|
11
|
+
date: 2020-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -70,14 +70,14 @@ dependencies:
|
|
70
70
|
requirements:
|
71
71
|
- - "~>"
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
version: '2
|
73
|
+
version: '3.2'
|
74
74
|
type: :runtime
|
75
75
|
prerelease: false
|
76
76
|
version_requirements: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
78
|
- - "~>"
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version: '2
|
80
|
+
version: '3.2'
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: shrine-url
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -376,7 +376,8 @@ files:
|
|
376
376
|
- lib/kithe/version.rb
|
377
377
|
- lib/shrine/plugins/kithe_accept_remote_url.rb
|
378
378
|
- lib/shrine/plugins/kithe_multi_cache.rb
|
379
|
-
- lib/shrine/plugins/
|
379
|
+
- lib/shrine/plugins/kithe_promotion_callbacks.rb
|
380
|
+
- lib/shrine/plugins/kithe_promotion_directives.rb
|
380
381
|
- lib/shrine/plugins/kithe_storage_location.rb
|
381
382
|
- lib/tasks/kithe_tasks.rake
|
382
383
|
- lib/vendor/icc/sRGB2014.icc
|
@@ -483,12 +484,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
483
484
|
requirements:
|
484
485
|
- - ">="
|
485
486
|
- !ruby/object:Gem::Version
|
486
|
-
version: '
|
487
|
+
version: '2.5'
|
487
488
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
488
489
|
requirements:
|
489
|
-
- - "
|
490
|
+
- - ">"
|
490
491
|
- !ruby/object:Gem::Version
|
491
|
-
version:
|
492
|
+
version: 1.3.1
|
492
493
|
requirements: []
|
493
494
|
rubygems_version: 3.0.3
|
494
495
|
signing_key:
|
@@ -1,138 +0,0 @@
|
|
1
|
-
class Shrine
|
2
|
-
module Plugins
|
3
|
-
# This adds some features around shrine promotion that we found useful for dealing
|
4
|
-
# with backgrounding promotion.
|
5
|
-
#
|
6
|
-
# * It will run shrine uploader metadata extraction routines on _any promotion_,
|
7
|
-
# also adding a `promoting: true` key to the shrine context for that metadata
|
8
|
-
# extraction. (Using shrine refresh_metadata plugin)
|
9
|
-
#
|
10
|
-
# * We separately give our Kithe::Asset model class an activemodel callback
|
11
|
-
# "promotion" hook. This plugin will call those callbacks around promotion (whether background
|
12
|
-
# or foreground) -- before, after, or around.
|
13
|
-
#
|
14
|
-
# If a callback does a `throw :abort` before promotion, it can cancel promotion. This could
|
15
|
-
# be used to cancel promotion for a validation failure of some kind -- you'd want to somehow
|
16
|
-
# store or notify what happened, otherwise to the app and it's users it will just look like
|
17
|
-
# the thing was never promoted for unknown reasons.
|
18
|
-
#
|
19
|
-
# After promotion hooks can be used to hook into things you want to do only after a promotion;
|
20
|
-
# since promotion is backgrounded it would be otherwise inconvenient to execute something
|
21
|
-
# only after promotion completes.
|
22
|
-
#
|
23
|
-
# The default Kithe::Asset hooks into after_promotion to run derivatives creation
|
24
|
-
# routines.
|
25
|
-
#
|
26
|
-
# * A special :promotion_directives key in the shrine context, which will be serialized
|
27
|
-
# and restored to be preserved even accross background promotion. It is intended to hold
|
28
|
-
# a hash of arbitrary key/values. The special key :skip_callbacks, when set to a truthy
|
29
|
-
# value, will prevent the promotion callbacks discussed above from happening. So if you want
|
30
|
-
# to save a Kithe::Asset and have promotion happen as usual, but _not_ trigger any callbacks
|
31
|
-
# (including derivative creation):
|
32
|
-
#
|
33
|
-
# some_asset.file = some_assignable_file
|
34
|
-
# some_asset.file_attacher.set_promotion_directives(skip_callbacks: true)
|
35
|
-
# some_asset.save!
|
36
|
-
#
|
37
|
-
# You can add other arbitrary keys which your own code in an uploader or promotion
|
38
|
-
# callback may consult, with `set_promotion_directives` as above. To consult, check
|
39
|
-
# attacher.promotion_directives[:some_key]
|
40
|
-
#
|
41
|
-
# You can also set promotion directives globally for Kithe::Asset or a sub-class, in
|
42
|
-
# a class method. Especially useful for batch processing.
|
43
|
-
#
|
44
|
-
# Kithe::Asset.promotion_directives = { promote: :inline, create_derivatives: :inline }
|
45
|
-
#
|
46
|
-
class KithePromotionHooks
|
47
|
-
# whitelist of allowed promotion_directive keys, so we can raise on typos but still
|
48
|
-
# be extensible. Also serves as some documentation of what directives available.
|
49
|
-
class_attribute :allowed_promotion_directives,
|
50
|
-
instance_writer: false,
|
51
|
-
default: [:promote, :skip_callbacks, :create_derivatives, :delete]
|
52
|
-
|
53
|
-
def self.load_dependencies(uploader, *)
|
54
|
-
uploader.plugin :refresh_metadata
|
55
|
-
uploader.plugin :backgrounding
|
56
|
-
end
|
57
|
-
|
58
|
-
module AttacherClassMethods
|
59
|
-
# Overridden to restore any serialized promotion_directives to context[:promotion_directives],
|
60
|
-
# in backgrounding promotion.
|
61
|
-
def load(data)
|
62
|
-
super.tap do |attacher|
|
63
|
-
if data["promotion_directives"]
|
64
|
-
attacher.context[:promotion_directives] = data["promotion_directives"]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
module AttacherMethods
|
71
|
-
|
72
|
-
# Set one or more promotion directives, in context[:promotion_directives], that
|
73
|
-
# will be serialized and restored to context for bg promotion. The values are intended
|
74
|
-
# to be simple strings or other json-serializable primitives.
|
75
|
-
#
|
76
|
-
# set_promotion_directives will merge it's results into existing promotion directives,
|
77
|
-
# existing keys will remain. So you can set multiple directives with multiple
|
78
|
-
# calls to set_promotion_directives, or pass multiple keys to one calls.
|
79
|
-
#
|
80
|
-
# @example
|
81
|
-
# some_model.file_attacher.set_promotion_directives(skip_callbacks: true)
|
82
|
-
# some_model.save!
|
83
|
-
def set_promotion_directives(hash)
|
84
|
-
# ActiveJob sometimes has trouble if there are symbols in there, somewhat
|
85
|
-
# unpredictably.
|
86
|
-
hash = hash.collect { |k, v| [k.to_s, v === Symbol ? v.to_s : v.to_s]}.to_h
|
87
|
-
|
88
|
-
unrecognized = hash.keys.collect(&:to_sym) - KithePromotionHooks.allowed_promotion_directives
|
89
|
-
unless unrecognized.length == 0
|
90
|
-
raise ArgumentError.new("Unrecognized promotion directive key: #{unrecognized.join('')}")
|
91
|
-
end
|
92
|
-
|
93
|
-
promotion_directives.merge!(hash)
|
94
|
-
end
|
95
|
-
|
96
|
-
# context[:promotion_directives], lazily initializing to hash for convenience.
|
97
|
-
def promotion_directives
|
98
|
-
context[:promotion_directives] ||= {}
|
99
|
-
end
|
100
|
-
|
101
|
-
# Overridden so our context[:promotion_directives] is serialized for
|
102
|
-
# backgrounding.
|
103
|
-
def dump
|
104
|
-
super.tap do |hash|
|
105
|
-
if context[:promotion_directives]
|
106
|
-
hash["promotion_directives"] = context[:promotion_directives]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Overridden to:
|
112
|
-
# a) refresh metadata as part of promotion (adds `promoting: true` to context for such)
|
113
|
-
# b) call promotion callbacks on Asset model, unless `promotion_directives["skip_callbacks"]`
|
114
|
-
# has been set.
|
115
|
-
def promote(uploaded_file = get, **options)
|
116
|
-
# insist on a metadata extraction, add a new key `promoting: true` in case
|
117
|
-
# anyone is interested.
|
118
|
-
|
119
|
-
uploaded_file.refresh_metadata!(**context.merge(options).merge(promoting: true))
|
120
|
-
|
121
|
-
# Now run ordinary promotion with activemodel callbacks from
|
122
|
-
# the Asset, which will automatically allow them to cancel promotion using
|
123
|
-
# ordinary activemodel callbacck technique of `throw :abort`.
|
124
|
-
if ( !promotion_directives["skip_callbacks"] &&
|
125
|
-
context[:record] &&
|
126
|
-
context[:record].class.respond_to?(:_promotion_callbacks) )
|
127
|
-
context[:record].run_callbacks(:promotion) do
|
128
|
-
super(uploaded_file, **options)
|
129
|
-
end
|
130
|
-
else
|
131
|
-
super(uploaded_file, **options)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
register_plugin(:kithe_promotion_hooks, KithePromotionHooks)
|
137
|
-
end
|
138
|
-
end
|