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
@@ -0,0 +1,30 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "delayed_paperclip/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = %q{kt-delayed_paperclip}
|
6
|
+
s.version = DelayedPaperclip::VERSION
|
7
|
+
|
8
|
+
s.authors = ["Adam Anderson", "Jesse Storimer", "Bert Goethals", "James Gifford", "Scott Carleton"]
|
9
|
+
s.summary = %q{Process your Paperclip attachments in the background}
|
10
|
+
s.description = %q{Process your Paperclip attachments in the background with ActiveJob}
|
11
|
+
s.email = %w{james@jamesrgifford.com scott@artsicle.com}
|
12
|
+
s.homepage = %q{https://github.com/adamtao/kt-delayed_paperclip}
|
13
|
+
|
14
|
+
s.required_ruby_version = ">= 2.0.0"
|
15
|
+
|
16
|
+
s.add_dependency 'kt-paperclip', "~> 6.4", ">= 6.4.1"
|
17
|
+
s.add_dependency 'activejob', ">= 4.2"
|
18
|
+
|
19
|
+
s.add_development_dependency 'mocha'
|
20
|
+
s.add_development_dependency "rspec", '< 3.0'
|
21
|
+
s.add_development_dependency 'sqlite3'
|
22
|
+
s.add_development_dependency 'appraisal'
|
23
|
+
s.add_development_dependency 'rake', '~> 10.5.0'
|
24
|
+
s.add_development_dependency 'bundler'
|
25
|
+
s.add_development_dependency 'activerecord'
|
26
|
+
s.add_development_dependency 'railties'
|
27
|
+
|
28
|
+
s.files = `git ls-files`.split("\n")
|
29
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
30
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
--- {}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'kt-paperclip'
|
2
|
+
require 'delayed_paperclip/process_job'
|
3
|
+
require 'delayed_paperclip/attachment'
|
4
|
+
require 'delayed_paperclip/url_generator'
|
5
|
+
require 'delayed_paperclip/railtie' if defined?(Rails)
|
6
|
+
|
7
|
+
module DelayedPaperclip
|
8
|
+
class << self
|
9
|
+
def options
|
10
|
+
@options ||= {
|
11
|
+
:background_job_class => DelayedPaperclip::ProcessJob,
|
12
|
+
:url_with_processing => true,
|
13
|
+
:processing_image_url => nil,
|
14
|
+
:queue => "paperclip"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def processor
|
19
|
+
options[:background_job_class]
|
20
|
+
end
|
21
|
+
|
22
|
+
def enqueue(instance_klass, instance_id, attachment_name)
|
23
|
+
processor.enqueue_delayed_paperclip(instance_klass, instance_id, attachment_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_job(instance_klass, instance_id, attachment_name)
|
27
|
+
instance = instance_klass.constantize.unscoped.where(id: instance_id).first
|
28
|
+
return if instance.blank?
|
29
|
+
|
30
|
+
instance.
|
31
|
+
send(attachment_name).
|
32
|
+
process_delayed!
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
module Glue
|
38
|
+
def self.included(base)
|
39
|
+
base.extend(ClassMethods)
|
40
|
+
base.send :include, InstanceMethods
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
|
46
|
+
def process_in_background(name, options = {})
|
47
|
+
# initialize as hash
|
48
|
+
paperclip_definitions[name][:delayed] = {}
|
49
|
+
|
50
|
+
# Set Defaults
|
51
|
+
only_process_default = paperclip_definitions[name][:only_process]
|
52
|
+
only_process_default ||= []
|
53
|
+
{
|
54
|
+
:priority => 0,
|
55
|
+
:only_process => only_process_default,
|
56
|
+
:url_with_processing => DelayedPaperclip.options[:url_with_processing],
|
57
|
+
:processing_image_url => DelayedPaperclip.options[:processing_image_url],
|
58
|
+
:queue => DelayedPaperclip.options[:queue]
|
59
|
+
}.each do |option, default|
|
60
|
+
paperclip_definitions[name][:delayed][option] = options.key?(option) ? options[option] : default
|
61
|
+
end
|
62
|
+
|
63
|
+
# Sets callback
|
64
|
+
if respond_to?(:after_commit)
|
65
|
+
after_commit :enqueue_delayed_processing
|
66
|
+
else
|
67
|
+
after_save :enqueue_delayed_processing
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def paperclip_definitions
|
72
|
+
if respond_to? :attachment_definitions
|
73
|
+
attachment_definitions
|
74
|
+
else
|
75
|
+
Paperclip::Tasks::Attachments.definitions_for(self)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module InstanceMethods
|
81
|
+
|
82
|
+
# First mark processing
|
83
|
+
# then enqueue
|
84
|
+
def enqueue_delayed_processing
|
85
|
+
mark_enqueue_delayed_processing
|
86
|
+
|
87
|
+
(@_enqued_for_processing || []).each do |name|
|
88
|
+
enqueue_post_processing_for(name)
|
89
|
+
end
|
90
|
+
@_enqued_for_processing_with_processing = []
|
91
|
+
@_enqued_for_processing = []
|
92
|
+
end
|
93
|
+
|
94
|
+
# setting each inididual NAME_processing to true, skipping the ActiveModel dirty setter
|
95
|
+
# Then immediately push the state to the database
|
96
|
+
def mark_enqueue_delayed_processing
|
97
|
+
unless @_enqued_for_processing_with_processing.blank? # catches nil and empty arrays
|
98
|
+
updates = @_enqued_for_processing_with_processing.collect{|n| "#{n}_processing = :true" }.join(", ")
|
99
|
+
updates = ActiveRecord::Base.send(:sanitize_sql_array, [updates, {:true => true}])
|
100
|
+
self.class.unscoped.where(:id => self.id).update_all(updates)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def enqueue_post_processing_for name
|
105
|
+
DelayedPaperclip.enqueue(self.class.name, read_attribute(:id), name.to_sym)
|
106
|
+
end
|
107
|
+
|
108
|
+
def prepare_enqueueing_for name
|
109
|
+
if self.attributes.has_key? "#{name}_processing"
|
110
|
+
write_attribute("#{name}_processing", true)
|
111
|
+
@_enqued_for_processing_with_processing ||= []
|
112
|
+
@_enqued_for_processing_with_processing << name
|
113
|
+
end
|
114
|
+
|
115
|
+
@_enqued_for_processing ||= []
|
116
|
+
@_enqued_for_processing << name
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module DelayedPaperclip
|
2
|
+
module Attachment
|
3
|
+
attr_accessor :job_is_processing
|
4
|
+
|
5
|
+
def delayed_options
|
6
|
+
options[:delayed]
|
7
|
+
end
|
8
|
+
|
9
|
+
# Attr accessor in Paperclip
|
10
|
+
def post_processing
|
11
|
+
!delay_processing? || split_processing?
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_processing=(value)
|
15
|
+
@post_processing_with_delay = value
|
16
|
+
end
|
17
|
+
|
18
|
+
# if nil, returns whether it has delayed options
|
19
|
+
# if set, then it returns
|
20
|
+
def delay_processing?
|
21
|
+
if @post_processing_with_delay.nil?
|
22
|
+
!!delayed_options
|
23
|
+
else
|
24
|
+
!@post_processing_with_delay
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def split_processing?
|
29
|
+
options[:only_process] && delayed_options &&
|
30
|
+
options[:only_process] != delayed_only_process
|
31
|
+
end
|
32
|
+
|
33
|
+
def processing?
|
34
|
+
column_name = :"#{@name}_processing?"
|
35
|
+
@instance.respond_to?(column_name) && @instance.send(column_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def processing_style?(style)
|
39
|
+
return false if !processing?
|
40
|
+
|
41
|
+
!split_processing? || delayed_only_process.include?(style)
|
42
|
+
end
|
43
|
+
|
44
|
+
def delayed_only_process
|
45
|
+
only_process = delayed_options.fetch(:only_process, []).dup
|
46
|
+
only_process = only_process.call(self) if only_process.respond_to?(:call)
|
47
|
+
only_process.map(&:to_sym)
|
48
|
+
end
|
49
|
+
|
50
|
+
def process_delayed!
|
51
|
+
self.job_is_processing = true
|
52
|
+
self.post_processing = true
|
53
|
+
reprocess!(*delayed_only_process)
|
54
|
+
self.job_is_processing = false
|
55
|
+
update_processing_column
|
56
|
+
end
|
57
|
+
|
58
|
+
def processing_image_url
|
59
|
+
processing_image_url = delayed_options[:processing_image_url]
|
60
|
+
processing_image_url = processing_image_url.call(self) if processing_image_url.respond_to?(:call)
|
61
|
+
processing_image_url
|
62
|
+
end
|
63
|
+
|
64
|
+
def save
|
65
|
+
was_dirty = @dirty
|
66
|
+
|
67
|
+
super.tap do
|
68
|
+
if delay_processing? && was_dirty
|
69
|
+
instance.prepare_enqueueing_for name
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def reprocess_without_delay!(*style_args)
|
75
|
+
@post_processing_with_delay = true
|
76
|
+
reprocess!(*style_args)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def update_processing_column
|
82
|
+
if instance.respond_to?(:"#{name}_processing?")
|
83
|
+
instance.send("#{name}_processing=", false)
|
84
|
+
instance.class.unscoped.where(instance.class.primary_key => instance.id).update_all({ "#{name}_processing" => false })
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "active_job"
|
2
|
+
|
3
|
+
module DelayedPaperclip
|
4
|
+
class ProcessJob < ActiveJob::Base
|
5
|
+
def self.enqueue_delayed_paperclip(instance_klass, instance_id, attachment_name)
|
6
|
+
queue_name = instance_klass.constantize.paperclip_definitions[attachment_name][:delayed][:queue]
|
7
|
+
set(:queue => queue_name).perform_later(instance_klass, instance_id, attachment_name.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform(instance_klass, instance_id, attachment_name)
|
11
|
+
DelayedPaperclip.process_job(instance_klass, instance_id, attachment_name.to_sym)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "paperclip"
|
2
|
+
require "delayed_paperclip"
|
3
|
+
|
4
|
+
module DelayedPaperclip
|
5
|
+
# On initialzation, include DelayedPaperclip
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer "delayed_paperclip.insert_into_active_record" do |app|
|
8
|
+
ActiveSupport.on_load :active_record do
|
9
|
+
DelayedPaperclip::Railtie.insert
|
10
|
+
end
|
11
|
+
|
12
|
+
if app.config.respond_to?(:delayed_paperclip_defaults)
|
13
|
+
DelayedPaperclip.options.merge!(app.config.delayed_paperclip_defaults)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Railtie
|
19
|
+
# Glue includes DelayedPaperclip Class Methods and Instance Methods into ActiveRecord
|
20
|
+
# Attachment and URL Generator extends Paperclip
|
21
|
+
def self.insert
|
22
|
+
ActiveRecord::Base.send(:include, DelayedPaperclip::Glue)
|
23
|
+
Paperclip::Attachment.prepend(DelayedPaperclip::Attachment)
|
24
|
+
Paperclip::Attachment.default_options[:url_generator] = DelayedPaperclip::UrlGenerator
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'paperclip/url_generator'
|
3
|
+
|
4
|
+
module DelayedPaperclip
|
5
|
+
class UrlGenerator < ::Paperclip::UrlGenerator
|
6
|
+
def initialize(attachment, _compatibility = nil)
|
7
|
+
@attachment = attachment
|
8
|
+
@attachment_options = attachment.options
|
9
|
+
end
|
10
|
+
|
11
|
+
def for(style_name, options)
|
12
|
+
most_appropriate_url = @attachment.processing_style?(style_name) ? most_appropriate_url(style_name) : most_appropriate_url()
|
13
|
+
timestamp_as_needed(
|
14
|
+
escape_url_as_needed(
|
15
|
+
@attachment_options[:interpolator].interpolate(most_appropriate_url, @attachment, style_name),
|
16
|
+
options
|
17
|
+
),
|
18
|
+
options)
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is a mess
|
22
|
+
def most_appropriate_url(style = nil)
|
23
|
+
if @attachment.processing_style?(style)
|
24
|
+
if @attachment.original_filename.nil? || delayed_default_url?(style)
|
25
|
+
|
26
|
+
if @attachment.delayed_options.nil? ||
|
27
|
+
@attachment.processing_image_url.nil? ||
|
28
|
+
!@attachment.processing?
|
29
|
+
default_url
|
30
|
+
else
|
31
|
+
@attachment.processing_image_url
|
32
|
+
end
|
33
|
+
|
34
|
+
else
|
35
|
+
@attachment_options[:url]
|
36
|
+
end
|
37
|
+
else
|
38
|
+
super()
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def timestamp_possible?
|
43
|
+
delayed_default_url? ? false : super
|
44
|
+
end
|
45
|
+
|
46
|
+
def delayed_default_url?(style = nil)
|
47
|
+
return false if @attachment.job_is_processing
|
48
|
+
return false if @attachment.dirty?
|
49
|
+
return false if not @attachment.delayed_options.try(:[], :url_with_processing)
|
50
|
+
return false if not processing?(style)
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def processing?(style)
|
57
|
+
return true if @attachment.processing?
|
58
|
+
return @attachment.processing_style?(style) if style
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,345 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DelayedPaperclip::Attachment do
|
4
|
+
before :each do
|
5
|
+
reset_dummy(dummy_options)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:dummy_options) { {} }
|
9
|
+
let(:dummy) { Dummy.create }
|
10
|
+
|
11
|
+
describe "#delayed_options" do
|
12
|
+
it "returns the specific options for delayed paperclip" do
|
13
|
+
expect(dummy.image.delayed_options).to eq({
|
14
|
+
:priority => 0,
|
15
|
+
:only_process => [],
|
16
|
+
:url_with_processing => true,
|
17
|
+
:processing_image_url => nil,
|
18
|
+
:queue => "paperclip"
|
19
|
+
})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#post_processing_with_delay" do
|
24
|
+
it "is true if delay_processing? is false" do
|
25
|
+
dummy.image.stubs(:delay_processing?).returns false
|
26
|
+
dummy.image.post_processing.should be_truthy
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is false if delay_processing? is true" do
|
30
|
+
dummy.image.stubs(:delay_processing?).returns true
|
31
|
+
dummy.image.post_processing.should be_falsey
|
32
|
+
end
|
33
|
+
|
34
|
+
context "on a non-delayed image" do
|
35
|
+
let(:dummy_options) { { with_processed: false } }
|
36
|
+
|
37
|
+
it "is false if delay_processing? is true" do
|
38
|
+
dummy.image.stubs(:delay_processing?).returns true
|
39
|
+
dummy.image.post_processing.should be_falsey
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#delay_processing?" do
|
45
|
+
it "returns delayed_options existence if post_processing is nil" do
|
46
|
+
dummy.image.post_processing = nil
|
47
|
+
dummy.image.delay_processing?.should be_truthy
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns inverse of post_processing if it's set" do
|
51
|
+
dummy.image.post_processing = true
|
52
|
+
dummy.image.delay_processing?.should be_falsey
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#processing?" do
|
57
|
+
it "delegates to the dummy instance" do
|
58
|
+
dummy.expects(:image_processing?)
|
59
|
+
dummy.image.processing?
|
60
|
+
end
|
61
|
+
|
62
|
+
context "without a processing column" do
|
63
|
+
let(:dummy_options) { { with_processed: false } }
|
64
|
+
|
65
|
+
it "returns false" do
|
66
|
+
expect(dummy.image.processing?).to be_falsey
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#processing_style?" do
|
72
|
+
let(:style) { :background }
|
73
|
+
let(:processing_style?) { dummy.image.processing_style?(style) }
|
74
|
+
|
75
|
+
context "without a processing column" do
|
76
|
+
let(:dummy_options) { { with_processed: true, process_column: false } }
|
77
|
+
|
78
|
+
specify { expect(processing_style?).to be_falsey }
|
79
|
+
end
|
80
|
+
|
81
|
+
context "with a processing column" do
|
82
|
+
context "when not processing" do
|
83
|
+
before { dummy.image_processing = false }
|
84
|
+
|
85
|
+
specify { expect(processing_style?).to be_falsey }
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when processing" do
|
89
|
+
before { dummy.image_processing = true }
|
90
|
+
|
91
|
+
context "when not split processing" do
|
92
|
+
specify { expect(processing_style?).to be_truthy }
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when split processing" do
|
96
|
+
context "when delayed :only_process is an Array" do
|
97
|
+
let(:dummy_options) { {
|
98
|
+
paperclip: {
|
99
|
+
styles: {
|
100
|
+
online: "400x400x",
|
101
|
+
background: "600x600x"
|
102
|
+
},
|
103
|
+
only_process: [:online]
|
104
|
+
},
|
105
|
+
|
106
|
+
only_process: [:background]
|
107
|
+
}}
|
108
|
+
|
109
|
+
specify { expect(processing_style?).to be }
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when delayed :only_process is callable" do
|
113
|
+
let(:dummy_options) { {
|
114
|
+
paperclip: {
|
115
|
+
styles: {
|
116
|
+
online: "400x400x",
|
117
|
+
background: "600x600x"
|
118
|
+
},
|
119
|
+
only_process: [:online]
|
120
|
+
},
|
121
|
+
|
122
|
+
only_process: lambda { |a| [:background] }
|
123
|
+
}}
|
124
|
+
|
125
|
+
specify { expect(processing_style?).to be }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#delayed_only_process" do
|
133
|
+
context "without only_process options" do
|
134
|
+
it "returns []" do
|
135
|
+
expect(dummy.image.delayed_only_process).to eq []
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "with only_process options" do
|
140
|
+
before :each do
|
141
|
+
reset_dummy(paperclip: { only_process: [:small, :large] } )
|
142
|
+
end
|
143
|
+
|
144
|
+
it "returns [:small, :large]" do
|
145
|
+
expect(dummy.image.delayed_only_process).to eq [:small, :large]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "with only_process set with callable" do
|
150
|
+
before :each do
|
151
|
+
reset_dummy(paperclip: { only_process: lambda { |a| [:small, :large] } } )
|
152
|
+
end
|
153
|
+
|
154
|
+
# Enable when https://github.com/thoughtbot/paperclip/pull/2289 is resolved
|
155
|
+
xit "returns [:small, :large]" do
|
156
|
+
expect(dummy.image.delayed_only_process).to eq [:small, :large]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#process_delayed!" do
|
162
|
+
it "sets job_is_processing to true" do
|
163
|
+
dummy.image.expects(:job_is_processing=).with(true).once
|
164
|
+
dummy.image.expects(:job_is_processing=).with(false).once
|
165
|
+
dummy.image.process_delayed!
|
166
|
+
end
|
167
|
+
|
168
|
+
it "sets post_processing to true" do
|
169
|
+
dummy.image.expects(:post_processing=).with(true).once
|
170
|
+
dummy.image.process_delayed!
|
171
|
+
end
|
172
|
+
|
173
|
+
context "without only_process options" do
|
174
|
+
it "calls reprocess!" do
|
175
|
+
dummy.image.expects(:reprocess!)
|
176
|
+
dummy.image.process_delayed!
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "with only_process options" do
|
181
|
+
before :each do
|
182
|
+
reset_dummy(paperclip: { only_process: [:small, :large] } )
|
183
|
+
end
|
184
|
+
|
185
|
+
it "calls reprocess! with options" do
|
186
|
+
dummy.image.expects(:reprocess!).with(:small, :large)
|
187
|
+
dummy.image.process_delayed!
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "with only_process set with callable" do
|
192
|
+
before :each do
|
193
|
+
reset_dummy(paperclip: { only_process: lambda { |a| [:small, :large] } } )
|
194
|
+
end
|
195
|
+
|
196
|
+
# Enable when https://github.com/thoughtbot/paperclip/pull/2289 is resolved
|
197
|
+
xit "calls reprocess! with options" do
|
198
|
+
dummy.image.expects(:reprocess!).with(:small, :large)
|
199
|
+
dummy.image.process_delayed!
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "#processing_image_url" do
|
205
|
+
context "no url" do
|
206
|
+
it "returns nil" do
|
207
|
+
dummy.image.processing_image_url.should be_nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context "static url" do
|
212
|
+
before :each do
|
213
|
+
reset_dummy(:processing_image_url => "/foo/bar.jpg")
|
214
|
+
end
|
215
|
+
|
216
|
+
it "returns given url" do
|
217
|
+
dummy.image.processing_image_url.should == "/foo/bar.jpg"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "proc" do
|
222
|
+
before :each do
|
223
|
+
reset_dummy(:processing_image_url => proc { "Hello/World" } )
|
224
|
+
end
|
225
|
+
|
226
|
+
it "returns evaluates proc" do
|
227
|
+
dummy.image.processing_image_url.should == "Hello/World"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "#update_processing_column" do
|
233
|
+
it "updates the column to false" do
|
234
|
+
dummy.update_attribute(:image_processing, true)
|
235
|
+
|
236
|
+
dummy.image.send(:update_processing_column)
|
237
|
+
|
238
|
+
dummy.reload.image_processing.should be_falsey
|
239
|
+
end
|
240
|
+
|
241
|
+
context 'with a default scope on the model excluding the instance' do
|
242
|
+
let(:dummy_options) do
|
243
|
+
{ :default_scope => lambda { Dummy.where(hidden: false) } }
|
244
|
+
end
|
245
|
+
|
246
|
+
let!(:dummy) { Dummy.create(hidden: true) }
|
247
|
+
|
248
|
+
specify { Dummy.count.should be 0 }
|
249
|
+
specify { Dummy.unscoped.count.should be 1 }
|
250
|
+
|
251
|
+
it "ignores the default scope and updates the column to false" do
|
252
|
+
dummy.update_attribute(:image_processing, true)
|
253
|
+
dummy.image.send(:update_processing_column)
|
254
|
+
dummy.reload.image_processing.should be_falsey
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe "#save" do
|
260
|
+
context "delay processing and it was dirty" do
|
261
|
+
before :each do
|
262
|
+
dummy.image.stubs(:delay_processing?).returns true
|
263
|
+
dummy.image.instance_variable_set(:@dirty, true)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "prepares the enqueing" do
|
267
|
+
dummy.expects(:prepare_enqueueing_for).with(:image)
|
268
|
+
dummy.image.save
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context "without dirty or delay_processing" do
|
273
|
+
it "does not prepare_enqueueing" do
|
274
|
+
dummy.expects(:prepare_enqueueing_for).with(:image).never
|
275
|
+
dummy.image.save
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe "#reprocess_without_delay!" do
|
281
|
+
it "sets post post_processing_with_delay and reprocesses with given args" do
|
282
|
+
dummy.image.expects(:reprocess!).with(:small)
|
283
|
+
dummy.image.reprocess_without_delay!(:small)
|
284
|
+
dummy.image.instance_variable_get(:@post_processing_with_delay).should == true
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
describe "#split_processing?" do
|
289
|
+
let(:split_processing?) { dummy.image.split_processing? }
|
290
|
+
|
291
|
+
let(:paperclip_styles) { {
|
292
|
+
online: "400x400x",
|
293
|
+
background: "600x600x"
|
294
|
+
} }
|
295
|
+
|
296
|
+
context ":only_process option is set on attachment" do
|
297
|
+
let(:dummy_options) { {
|
298
|
+
paperclip: {
|
299
|
+
styles: paperclip_styles,
|
300
|
+
only_process: [:online]
|
301
|
+
},
|
302
|
+
|
303
|
+
only_process: delayed_only_process
|
304
|
+
}}
|
305
|
+
|
306
|
+
context "processing different styles in background" do
|
307
|
+
context "when delayed :only_process is an Array" do
|
308
|
+
let(:delayed_only_process) { [:background] }
|
309
|
+
|
310
|
+
specify { expect(split_processing?).to be true }
|
311
|
+
end
|
312
|
+
|
313
|
+
context "when delayed :only_process is callable" do
|
314
|
+
let(:delayed_only_process) { lambda { |a| [:background] } }
|
315
|
+
|
316
|
+
specify { expect(split_processing?).to be true }
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
context "processing same styles in background" do
|
321
|
+
context "when delayed :only_process is an Array" do
|
322
|
+
let(:delayed_only_process) { [:online] }
|
323
|
+
|
324
|
+
specify { expect(split_processing?).to be false }
|
325
|
+
end
|
326
|
+
|
327
|
+
context "when delayed :only_process is callable" do
|
328
|
+
let(:delayed_only_process) { lambda { |a| [:online] } }
|
329
|
+
|
330
|
+
specify { expect(split_processing?).to be false }
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
context ":only_process option is not set on attachment" do
|
336
|
+
let(:dummy_options) { {
|
337
|
+
paperclip: {
|
338
|
+
styles: paperclip_styles
|
339
|
+
}
|
340
|
+
}}
|
341
|
+
|
342
|
+
specify { expect(split_processing?).to be false }
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|