kt-delayed_paperclip 3.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +36 -0
- data/Appraisals +12 -0
- data/CONTRIBUTING +16 -0
- data/ChangeLog +1 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +314 -0
- data/Rakefile +20 -0
- data/delayed_paperclip.gemspec +30 -0
- data/gemfiles/.bundle/config +1 -0
- data/gemfiles/4.2.gemfile +7 -0
- data/gemfiles/5.0.gemfile +7 -0
- data/gemfiles/5.0_paperclip_master.gemfile +8 -0
- data/lib/delayed_paperclip.rb +119 -0
- data/lib/delayed_paperclip/attachment.rb +89 -0
- data/lib/delayed_paperclip/process_job.rb +14 -0
- data/lib/delayed_paperclip/railtie.rb +27 -0
- data/lib/delayed_paperclip/url_generator.rb +61 -0
- data/lib/delayed_paperclip/version.rb +3 -0
- data/lib/kt-delayed_paperclip.rb +2 -0
- data/spec/delayed_paperclip/attachment_spec.rb +345 -0
- data/spec/delayed_paperclip/class_methods_spec.rb +95 -0
- data/spec/delayed_paperclip/instance_methods_spec.rb +71 -0
- data/spec/delayed_paperclip/url_generator_spec.rb +273 -0
- data/spec/delayed_paperclip_spec.rb +66 -0
- data/spec/fixtures/12k.png +0 -0
- data/spec/fixtures/missing.png +0 -0
- data/spec/integration/base_delayed_paperclip_spec.rb +23 -0
- data/spec/integration/examples/base.rb +326 -0
- data/spec/integration/process_job_spec.rb +26 -0
- data/spec/spec_helper.rb +122 -0
- data/spec/tmp/.keep +0 -0
- metadata +238 -0
Binary file
|
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Base Delayed Paperclip Integration" do
|
4
|
+
let(:dummy) { Dummy.create }
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
reset_dummy(paperclip: { default_url: "/../../fixtures/missing.png" })
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "double save" do
|
11
|
+
before :each do
|
12
|
+
dummy.image_processing.should be_falsey
|
13
|
+
dummy.image = File.open("#{ROOT}/fixtures/12k.png")
|
14
|
+
dummy.save!
|
15
|
+
end
|
16
|
+
|
17
|
+
it "processing column remains true" do
|
18
|
+
dummy.image_processing.should be_truthy
|
19
|
+
dummy.save!
|
20
|
+
dummy.image_processing.should be_truthy
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,326 @@
|
|
1
|
+
shared_examples "base usage" do
|
2
|
+
before :each do
|
3
|
+
DelayedPaperclip.options[:url_with_processing] = true
|
4
|
+
reset_dummy
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "normal paperclip" do
|
8
|
+
before :each do
|
9
|
+
DelayedPaperclip.options[:url_with_processing] = false
|
10
|
+
reset_dummy :with_processed => false
|
11
|
+
end
|
12
|
+
|
13
|
+
it "allows normal paperclip functionality" do
|
14
|
+
Paperclip::Attachment.any_instance.expects(:post_process)
|
15
|
+
dummy.image.delay_processing?.should be_falsey
|
16
|
+
dummy.image.post_processing.should be_truthy
|
17
|
+
dummy.save.should be_truthy
|
18
|
+
File.exists?(dummy.image.path).should be_truthy
|
19
|
+
end
|
20
|
+
|
21
|
+
context "missing url" do
|
22
|
+
it "does not return missing url if false globally" do
|
23
|
+
dummy.save!
|
24
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
25
|
+
process_jobs
|
26
|
+
dummy.reload
|
27
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "does not return missing url if false on instance" do
|
31
|
+
reset_dummy :with_processed => false, :url_with_processing => false
|
32
|
+
dummy.save!
|
33
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
34
|
+
process_jobs # There aren't any
|
35
|
+
dummy.reload
|
36
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO: somewhat duplicate test of the above
|
41
|
+
context "original url without processing column" do
|
42
|
+
it "works normally" do
|
43
|
+
dummy.save!
|
44
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "set post processing" do
|
50
|
+
before :each do
|
51
|
+
reset_dummy :with_processed => true
|
52
|
+
dummy.image.post_processing = true
|
53
|
+
end
|
54
|
+
it "has delay_processing is false" do
|
55
|
+
dummy.image.delay_processing?.should be_falsey
|
56
|
+
end
|
57
|
+
|
58
|
+
it "post processing returns true" do
|
59
|
+
dummy.image.post_processing.should be_truthy
|
60
|
+
end
|
61
|
+
|
62
|
+
it "writes the file" do
|
63
|
+
dummy.save
|
64
|
+
File.exists?(dummy.image.path).should be_truthy
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "without processing column" do
|
69
|
+
before :each do
|
70
|
+
build_dummy_table(false)
|
71
|
+
reset_class "Dummy", :with_processed => true
|
72
|
+
Paperclip::Attachment.any_instance.expects(:post_process).never
|
73
|
+
end
|
74
|
+
|
75
|
+
it "delays processing" do
|
76
|
+
dummy.image.delay_processing?.should be_truthy
|
77
|
+
end
|
78
|
+
|
79
|
+
it "post_processing is false" do
|
80
|
+
dummy.image.post_processing.should be_falsey
|
81
|
+
end
|
82
|
+
|
83
|
+
it "has file after save" do
|
84
|
+
dummy.save
|
85
|
+
File.exists?(dummy.image.path).should be_truthy
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "jobs count" do
|
91
|
+
it "increments by 1" do
|
92
|
+
original_job_count = jobs_count
|
93
|
+
dummy.save
|
94
|
+
jobs_count.should == original_job_count + 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "processing column not altered" do
|
99
|
+
it "resets after job finished" do
|
100
|
+
dummy.save!
|
101
|
+
dummy.image_processing?.should be_truthy
|
102
|
+
process_jobs
|
103
|
+
dummy.reload.image_processing?.should be_falsey
|
104
|
+
end
|
105
|
+
|
106
|
+
context "with error" do
|
107
|
+
it "stays true even if errored" do
|
108
|
+
Paperclip::Attachment.any_instance.stubs(:reprocess!).raises(StandardError.new('oops'))
|
109
|
+
|
110
|
+
dummy.save!
|
111
|
+
dummy.image_processing?.should be_truthy
|
112
|
+
|
113
|
+
expect do
|
114
|
+
process_jobs
|
115
|
+
end.to raise_error(StandardError)
|
116
|
+
|
117
|
+
dummy.image_processing?.should be_truthy
|
118
|
+
dummy.reload.image_processing?.should be_truthy
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# TODO: test appears redundant
|
124
|
+
describe "processing is true for new record" do
|
125
|
+
it "is true" do
|
126
|
+
dummy.image_processing?.should be_falsey
|
127
|
+
dummy.new_record?.should be_truthy
|
128
|
+
dummy.save!
|
129
|
+
dummy.reload.image_processing?.should be_truthy
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "urls" do
|
134
|
+
it "returns missing url until job is finished" do
|
135
|
+
dummy.save!
|
136
|
+
dummy.image.url.should start_with("/images/original/missing.png")
|
137
|
+
process_jobs
|
138
|
+
dummy.reload
|
139
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
140
|
+
end
|
141
|
+
|
142
|
+
context "processing url" do
|
143
|
+
before :each do
|
144
|
+
reset_dummy :processing_image_url => "/images/original/processing.png"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "returns processing url while processing" do
|
148
|
+
dummy.save!
|
149
|
+
dummy.image.url.should start_with("/images/original/processing.png")
|
150
|
+
process_jobs
|
151
|
+
dummy.reload
|
152
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
153
|
+
end
|
154
|
+
|
155
|
+
context "defaults to missing when no file" do
|
156
|
+
it "fallsback gracefully" do
|
157
|
+
dummy = Dummy.new()
|
158
|
+
dummy.save!
|
159
|
+
dummy.reload.image.url.should start_with("/images/original/missing.png")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "same url if same file assigned" do
|
165
|
+
it "falls to missing while processing" do
|
166
|
+
dummy.save!
|
167
|
+
dummy.image = File.open("#{ROOT}/fixtures/12k.png")
|
168
|
+
dummy.save!
|
169
|
+
dummy.image.url.should start_with("/images/original/missing.png")
|
170
|
+
process_jobs
|
171
|
+
dummy.reload.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "callbacks" do
|
178
|
+
context "paperclip callback" do
|
179
|
+
before :each do
|
180
|
+
Dummy.send(:define_method, :done_processing) { puts 'done' }
|
181
|
+
Dummy.send(:after_image_post_process, :done_processing)
|
182
|
+
Dummy.any_instance.expects(:done_processing).once
|
183
|
+
end
|
184
|
+
|
185
|
+
it "observes after_image_post_process" do
|
186
|
+
dummy.save!
|
187
|
+
process_jobs
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "after_update callback" do
|
192
|
+
before :each do
|
193
|
+
reset_class "Dummy", :with_processed => true,
|
194
|
+
:with_after_update_callback => true
|
195
|
+
end
|
196
|
+
|
197
|
+
it "hits after_update" do
|
198
|
+
Dummy.any_instance.expects(:reprocess).once
|
199
|
+
dummy.save!
|
200
|
+
process_jobs
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "only_process option" do
|
206
|
+
|
207
|
+
# TODO: This test must be faulty
|
208
|
+
# https://github.com/jrgifford/delayed_paperclip/issues/40
|
209
|
+
context "passed just to delayed_paperclip argument" do
|
210
|
+
before :each do
|
211
|
+
reset_class "Dummy", :with_processed => true, :only_process => [:thumbnail]
|
212
|
+
end
|
213
|
+
|
214
|
+
it "reprocesses just those" do
|
215
|
+
Paperclip::Attachment.any_instance.expects(:reprocess!).with(:thumbnail).once
|
216
|
+
dummy.save!
|
217
|
+
process_jobs
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "inherits from paperclip options" do
|
222
|
+
before :each do
|
223
|
+
reset_class "Dummy", :with_processed => true, :paperclip => { :only_process => [:thumbnail] }
|
224
|
+
end
|
225
|
+
|
226
|
+
it "reprocesses just those" do
|
227
|
+
Paperclip::Attachment.any_instance.expects(:reprocess!).with(:thumbnail).once
|
228
|
+
dummy.save!
|
229
|
+
process_jobs
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "converts image formats" do
|
235
|
+
before :each do
|
236
|
+
reset_class "Dummy", :with_processed => true,
|
237
|
+
:paperclip => {
|
238
|
+
:styles => {
|
239
|
+
:thumbnail => ['12x12', :jpg]
|
240
|
+
}
|
241
|
+
}
|
242
|
+
end
|
243
|
+
|
244
|
+
it "observes the option" do
|
245
|
+
dummy.save!
|
246
|
+
process_jobs
|
247
|
+
dummy.reload.image.url(:thumbnail).should start_with("/system/dummies/images/000/000/001/thumbnail/12k.jpg")
|
248
|
+
File.exists?(dummy.image.path).should be_truthy
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "reprocess_without_delay" do
|
253
|
+
before :each do
|
254
|
+
DelayedPaperclip.options[:url_with_processing] = true
|
255
|
+
reset_dummy :paperclip => {
|
256
|
+
:styles => {
|
257
|
+
:thumbnail => '12x12'
|
258
|
+
}
|
259
|
+
}
|
260
|
+
end
|
261
|
+
|
262
|
+
it "does not increase jobs count" do
|
263
|
+
dummy.save!
|
264
|
+
dummy.image_processing?.should be_truthy
|
265
|
+
process_jobs
|
266
|
+
dummy.reload.image_processing?.should be_falsey
|
267
|
+
|
268
|
+
Paperclip::Attachment.any_instance.expects(:reprocess!).once
|
269
|
+
|
270
|
+
existing_jobs = jobs_count
|
271
|
+
dummy.image.reprocess_without_delay!(:thumbnail)
|
272
|
+
existing_jobs.should == jobs_count
|
273
|
+
|
274
|
+
dummy.image_processing?.should be_falsey
|
275
|
+
File.exists?(dummy.image.path).should be_truthy
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
describe "reprocessing_url" do
|
281
|
+
|
282
|
+
context "interpolation of styles" do
|
283
|
+
before :each do
|
284
|
+
reset_dummy :processing_image_url => "/images/:style/processing.png",
|
285
|
+
:paperclip => {
|
286
|
+
:styles => {
|
287
|
+
:thumbnail => '12x12'
|
288
|
+
}
|
289
|
+
}
|
290
|
+
end
|
291
|
+
|
292
|
+
it "interpolates unporcessed image" do
|
293
|
+
dummy.save!
|
294
|
+
dummy.image.url.should start_with("/images/original/processing.png")
|
295
|
+
dummy.image.url(:thumbnail).should start_with("/images/thumbnail/processing.png")
|
296
|
+
process_jobs
|
297
|
+
dummy.reload.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context "proc for reprocessing_url" do
|
302
|
+
before :each do
|
303
|
+
reset_dummy :processing_image_url => lambda { |attachment| attachment.instance.reprocessing_url }
|
304
|
+
Dummy.send(:define_method, :reprocessing_url) { 'done' }
|
305
|
+
end
|
306
|
+
|
307
|
+
it "calls it correctly" do
|
308
|
+
dummy.save!
|
309
|
+
dummy.image.url.should start_with("done")
|
310
|
+
process_jobs
|
311
|
+
dummy.reload
|
312
|
+
dummy.image.url.should start_with("/system/dummies/images/000/000/001/original/12k.png")
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "queue option" do
|
318
|
+
it "enqueues job with given queue name" do
|
319
|
+
reset_dummy :queue => "custom"
|
320
|
+
|
321
|
+
expect do
|
322
|
+
dummy.save!
|
323
|
+
end.to change { jobs_count("custom") }.by(1)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "DelayedJob::ProcessJob" do
|
4
|
+
before :each do
|
5
|
+
ActiveJob::Base.queue_adapter = :test
|
6
|
+
ActiveJob::Base.logger = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:dummy) { Dummy.new(:image => File.open("#{ROOT}/fixtures/12k.png")) }
|
10
|
+
|
11
|
+
describe "integration tests" do
|
12
|
+
include_examples "base usage"
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_jobs
|
16
|
+
ActiveJob::Base.queue_adapter.enqueued_jobs.each do |job|
|
17
|
+
job[:job].send(:perform_now, *job[:args])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def jobs_count(queue = "paperclip")
|
22
|
+
ActiveJob::Base.queue_adapter.enqueued_jobs.count do |job|
|
23
|
+
job[:queue] == queue
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
+
|
4
|
+
require 'rails'
|
5
|
+
require 'active_record'
|
6
|
+
require 'rspec'
|
7
|
+
require 'mocha/api'
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'pry'
|
11
|
+
rescue LoadError
|
12
|
+
# Pry is not available, just ignore.
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'paperclip/railtie'
|
16
|
+
Paperclip::Railtie.insert
|
17
|
+
|
18
|
+
require 'delayed_paperclip/railtie'
|
19
|
+
DelayedPaperclip::Railtie.insert
|
20
|
+
|
21
|
+
# silence deprecation warnings in rails 4.2
|
22
|
+
# in Rails 5 this setting is deprecated and has no effect
|
23
|
+
if ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks=) && Rails::VERSION::MAJOR < 5
|
24
|
+
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Connect to sqlite
|
28
|
+
ActiveRecord::Base.establish_connection(
|
29
|
+
"adapter" => "sqlite3",
|
30
|
+
"database" => ":memory:"
|
31
|
+
)
|
32
|
+
|
33
|
+
# Path for filesystem writing
|
34
|
+
ROOT = Pathname.new(File.expand_path("../.", __FILE__))
|
35
|
+
|
36
|
+
logger = Logger.new(ROOT.join("tmp/debug.log"))
|
37
|
+
ActiveRecord::Base.logger = logger
|
38
|
+
ActiveJob::Base.logger = logger
|
39
|
+
Paperclip.logger = logger
|
40
|
+
|
41
|
+
RSpec.configure do |config|
|
42
|
+
config.mock_with :mocha
|
43
|
+
|
44
|
+
config.order = :random
|
45
|
+
|
46
|
+
config.filter_run focus: true
|
47
|
+
config.run_all_when_everything_filtered = true
|
48
|
+
|
49
|
+
config.before(:each) do
|
50
|
+
reset_global_default_options
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def reset_global_default_options
|
55
|
+
DelayedPaperclip.options.merge!({
|
56
|
+
:background_job_class => DelayedPaperclip::ProcessJob,
|
57
|
+
:url_with_processing => true,
|
58
|
+
:processing_image_url => nil
|
59
|
+
})
|
60
|
+
end
|
61
|
+
|
62
|
+
# In order to not duplicate code directly from Paperclip's spec support
|
63
|
+
# We're requiring the MockInterpolator object to be used
|
64
|
+
require Gem.find_files("../spec/support/mock_interpolator").first
|
65
|
+
|
66
|
+
Dir["./spec/integration/examples/*.rb"].sort.each { |f| require f }
|
67
|
+
|
68
|
+
# Reset table and class with image_processing column or not
|
69
|
+
def reset_dummy(options = {})
|
70
|
+
options[:with_processed] = true unless options.key?(:with_processed)
|
71
|
+
options[:processed_column] = options[:with_processed] unless options.has_key?(:processed_column)
|
72
|
+
|
73
|
+
build_dummy_table(options.delete(:processed_column))
|
74
|
+
reset_class("Dummy", options)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Dummy Table for images
|
78
|
+
# with or without image_processing column
|
79
|
+
def build_dummy_table(with_column)
|
80
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |t|
|
81
|
+
t.string :name
|
82
|
+
t.string :image_file_name
|
83
|
+
t.string :image_content_type
|
84
|
+
t.integer :image_file_size
|
85
|
+
t.datetime :image_updated_at
|
86
|
+
t.boolean :hidden, :default => false
|
87
|
+
t.boolean(:image_processing, :default => false) if with_column
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def reset_class(class_name, options)
|
92
|
+
# setup class and include paperclip
|
93
|
+
options[:paperclip] = {} if options[:paperclip].nil?
|
94
|
+
ActiveRecord::Base.send(:include, Paperclip::Glue)
|
95
|
+
Object.send(:remove_const, class_name) rescue nil
|
96
|
+
|
97
|
+
# Set class as a constant
|
98
|
+
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
|
99
|
+
|
100
|
+
# Setup class with paperclip and delayed paperclip
|
101
|
+
klass.class_eval do
|
102
|
+
include Paperclip::Glue
|
103
|
+
|
104
|
+
has_attached_file :image, options.delete(:paperclip)
|
105
|
+
|
106
|
+
validates_attachment :image, :content_type => { :content_type => "image/png" }
|
107
|
+
|
108
|
+
process_in_background :image, options if options[:with_processed]
|
109
|
+
|
110
|
+
after_update :reprocess if options[:with_after_update_callback]
|
111
|
+
|
112
|
+
default_scope options[:default_scope] if options[:default_scope]
|
113
|
+
|
114
|
+
def reprocess
|
115
|
+
image.reprocess!
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
Rails.stubs(:root).returns(ROOT.join("tmp"))
|
120
|
+
klass.reset_column_information
|
121
|
+
klass
|
122
|
+
end
|