delayed_paperclip 0.7.2 → 2.4.0.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.
- data/README.textile +2 -2
- data/Rakefile +23 -2
- data/init.rb +4 -0
- data/lib/delayed_paperclip/attachment.rb +76 -0
- data/lib/delayed_paperclip/jobs/delayed_job.rb +20 -5
- data/lib/delayed_paperclip/jobs/resque.rb +2 -0
- data/lib/delayed_paperclip/jobs.rb +6 -0
- data/lib/delayed_paperclip/railtie.rb +21 -0
- data/lib/delayed_paperclip.rb +19 -80
- data/rails/init.rb +2 -1
- data/test/base_delayed_paperclip_test.rb +140 -0
- data/test/delayed_paperclip_test.rb +24 -115
- data/test/resque_paperclip_test.rb +14 -36
- data/test/test_helper.rb +22 -29
- metadata +25 -32
- data/.gitignore +0 -4
- data/.rvmrc +0 -1
- data/CONTRIBUTING +0 -16
- data/Gemfile +0 -3
- data/delayed_paperclip.gemspec +0 -21
data/README.textile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
h1. Delayed::Paperclip
|
1
|
+
h1. Delayed::Paperclip !https://secure.travis-ci.org/jstorimer/delayed_paperclip.png!
|
2
2
|
|
3
3
|
Delayed_paperclip lets you process your "Paperclip":http://github.com/thoughtbot/paperclip attachments in a background task with "delayed_job":http://github.com/tobi/delayed_job or "Resque":http://github.com/defunkt/resque.
|
4
4
|
|
@@ -84,7 +84,7 @@ To have the missing image url be outputted by paperclip while the image is being
|
|
84
84
|
|
85
85
|
h2. What if I'm not using images?
|
86
86
|
|
87
|
-
|
87
|
+
This library works no matter what kind of post-processing you are doing with Paperclip.
|
88
88
|
|
89
89
|
h2. Does it work with s3?
|
90
90
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'appraisal'
|
5
|
+
|
1
6
|
require 'rake'
|
2
7
|
require 'rake/testtask'
|
3
8
|
|
4
9
|
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
5
10
|
|
11
|
+
|
6
12
|
desc 'Default: run unit tests.'
|
7
|
-
task :default => :
|
13
|
+
task :default => [:clean, 'appraisal:install', :all]
|
14
|
+
|
15
|
+
desc 'Test the paperclip plugin under all supported Rails versions.'
|
16
|
+
task :all do |t|
|
17
|
+
exec('rake appraisal test')
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Clean up files.'
|
21
|
+
task :clean do |t|
|
22
|
+
FileUtils.rm_rf "doc"
|
23
|
+
FileUtils.rm_rf "tmp"
|
24
|
+
FileUtils.rm_rf "pkg"
|
25
|
+
FileUtils.rm_rf "public"
|
26
|
+
FileUtils.rm "test/debug.log" rescue nil
|
27
|
+
FileUtils.rm "test/paperclip.db" rescue nil
|
28
|
+
Dir.glob("paperclip-*.gem").each{|f| FileUtils.rm f }
|
29
|
+
end
|
8
30
|
|
9
31
|
desc 'Test the paperclip plugin.'
|
10
32
|
Rake::TestTask.new(:test) do |t|
|
@@ -12,4 +34,3 @@ Rake::TestTask.new(:test) do |t|
|
|
12
34
|
t.pattern = 'test/**/*_test.rb'
|
13
35
|
t.verbose = true
|
14
36
|
end
|
15
|
-
|
data/init.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module DelayedPaperclip
|
2
|
+
module Attachment
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send :include, InstanceMethods
|
6
|
+
base.send :attr_accessor, :job_is_processing
|
7
|
+
base.alias_method_chain :post_processing, :delay
|
8
|
+
base.alias_method_chain :post_processing=, :delay
|
9
|
+
base.alias_method_chain :save, :prepare_enqueueing
|
10
|
+
base.alias_method_chain :url, :processed
|
11
|
+
base.alias_method_chain :post_process_styles, :processing
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
|
16
|
+
def post_processing_with_delay
|
17
|
+
!delay_processing?
|
18
|
+
end
|
19
|
+
|
20
|
+
def post_processing_with_delay=(value)
|
21
|
+
@post_processing_with_delay = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def delay_processing?
|
25
|
+
if @post_processing_with_delay.nil?
|
26
|
+
!!@instance.class.attachment_definitions[@name][:delayed]
|
27
|
+
else
|
28
|
+
!@post_processing_with_delay
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def processing?
|
33
|
+
@instance.send(:"#{@name}_processing?")
|
34
|
+
end
|
35
|
+
|
36
|
+
def process_delayed!
|
37
|
+
self.job_is_processing = true
|
38
|
+
reprocess!
|
39
|
+
self.job_is_processing = false
|
40
|
+
end
|
41
|
+
|
42
|
+
def post_process_styles_with_processing(*args)
|
43
|
+
post_process_styles_without_processing(*args)
|
44
|
+
instance.update_attribute("#{name}_processing", false) if instance.respond_to?(:"#{name}_processing?")
|
45
|
+
end
|
46
|
+
|
47
|
+
def save_with_prepare_enqueueing
|
48
|
+
was_dirty = @dirty
|
49
|
+
save_without_prepare_enqueueing.tap do
|
50
|
+
if delay_processing? && was_dirty
|
51
|
+
instance.prepare_enqueueing_for name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def url_with_processed style = default_style, include_updated_timestamp = @use_timestamp
|
57
|
+
return url_without_processed style, include_updated_timestamp if !@instance.class.attachment_definitions[@name][:delayed].try(:[], :url_with_processing) || job_is_processing
|
58
|
+
|
59
|
+
if !@instance.respond_to?(:"#{name}_processing?")
|
60
|
+
url_without_processed style, include_updated_timestamp
|
61
|
+
else
|
62
|
+
if !processing?
|
63
|
+
url_without_processed style, include_updated_timestamp
|
64
|
+
else
|
65
|
+
if dirty?
|
66
|
+
url_without_processed style, include_updated_timestamp
|
67
|
+
else
|
68
|
+
interpolate(@default_url, style)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,12 +1,27 @@
|
|
1
|
+
require 'delayed_job'
|
2
|
+
|
1
3
|
module DelayedPaperclip
|
2
4
|
module Jobs
|
3
5
|
class DelayedJob < Struct.new(:instance_klass, :instance_id, :attachment_name)
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
if defined?(::Delayed::DeserializationError) # this is available in newer versions of DelayedJob. Using the newee Job api thus.
|
8
|
+
|
9
|
+
def self.enqueue_delayed_paperclip(instance_klass, instance_id, attachment_name)
|
10
|
+
::Delayed::Job.enqueue(
|
11
|
+
:payload_object => new(instance_klass, instance_id, attachment_name),
|
12
|
+
:priority => instance_klass.constantize.attachment_definitions[attachment_name][:delayed][:priority].to_i
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
else
|
17
|
+
|
18
|
+
def self.enqueue_delayed_paperclip(instance_klass, instance_id, attachment_name)
|
19
|
+
::Delayed::Job.enqueue(
|
20
|
+
new(instance_klass, instance_id, attachment_name),
|
21
|
+
instance_klass.constantize.attachment_definitions[attachment_name][:delayed][:priority].to_i
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
10
25
|
end
|
11
26
|
|
12
27
|
def perform
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'delayed_paperclip'
|
2
|
+
|
3
|
+
module DelayedPaperclip
|
4
|
+
if defined? Rails::Railtie
|
5
|
+
require 'rails'
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer 'delayed_paperclip.insert_into_active_record' do
|
8
|
+
ActiveSupport.on_load :paperclip do
|
9
|
+
DelayedPaperclip::Railtie.insert
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Railtie
|
16
|
+
def self.insert
|
17
|
+
ActiveRecord::Base.send(:include, DelayedPaperclip)
|
18
|
+
Paperclip::Attachment.send :include, DelayedPaperclip::Attachment
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/delayed_paperclip.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require 'delayed_paperclip'
|
4
|
-
require 'delayed_paperclip/jobs/delayed_job'
|
5
|
-
require 'delayed_paperclip/jobs/resque'
|
1
|
+
require 'delayed_paperclip/jobs'
|
2
|
+
require 'delayed_paperclip/attachment'
|
6
3
|
|
7
4
|
module DelayedPaperclip
|
8
5
|
|
9
6
|
class << self
|
10
7
|
|
11
8
|
def options
|
12
|
-
options ||= {
|
13
|
-
:background_job_class => detect_background_task
|
9
|
+
@options ||= {
|
10
|
+
:background_job_class => detect_background_task,
|
11
|
+
:url_with_processing => true
|
14
12
|
}
|
15
13
|
end
|
16
14
|
|
@@ -45,7 +43,12 @@ module DelayedPaperclip
|
|
45
43
|
include InstanceMethods
|
46
44
|
|
47
45
|
attachment_definitions[name][:delayed] = {}
|
48
|
-
|
46
|
+
{
|
47
|
+
:priority => 0,
|
48
|
+
:url_with_processing => DelayedPaperclip.options[:url_with_processing]
|
49
|
+
}.each do |option, default|
|
50
|
+
attachment_definitions[name][:delayed][option] = options.key?(option) ? options[option] : default
|
51
|
+
end
|
49
52
|
|
50
53
|
if respond_to?(:after_commit)
|
51
54
|
after_commit :enqueue_delayed_processing
|
@@ -60,15 +63,8 @@ module DelayedPaperclip
|
|
60
63
|
# setting each inididual NAME_processing to true, skipping the ActiveModel dirty setter
|
61
64
|
# Then immediately push the state to the database
|
62
65
|
def mark_enqueue_delayed_processing
|
63
|
-
|
64
|
-
|
65
|
-
if self.attributes.has_key? "#{name}_processing"
|
66
|
-
write_attribute("#{name}_processing", true)
|
67
|
-
processing << name
|
68
|
-
end
|
69
|
-
end
|
70
|
-
unless processing.empty?
|
71
|
-
updates = processing.collect{|n| "#{n}_processing = :true" }.join(", ")
|
66
|
+
unless @_enqued_for_processing_with_processing.blank? # catches nil and empy arrays
|
67
|
+
updates = @_enqued_for_processing_with_processing.collect{|n| "#{n}_processing = :true" }.join(", ")
|
72
68
|
updates = ActiveRecord::Base.send(:sanitize_sql_array, [updates, {:true => true}])
|
73
69
|
self.class.update_all(updates, "id = #{self.id}")
|
74
70
|
end
|
@@ -81,6 +77,7 @@ module DelayedPaperclip
|
|
81
77
|
(@_enqued_for_processing || []).each do |name|
|
82
78
|
enqueue_post_processing_for(name)
|
83
79
|
end
|
80
|
+
@_enqued_for_processing_with_processing = []
|
84
81
|
@_enqued_for_processing = []
|
85
82
|
end
|
86
83
|
|
@@ -88,73 +85,15 @@ module DelayedPaperclip
|
|
88
85
|
DelayedPaperclip.enqueue(self.class.name, read_attribute(:id), name.to_sym)
|
89
86
|
end
|
90
87
|
|
91
|
-
def attachment_for name
|
92
|
-
@_paperclip_attachments ||= {}
|
93
|
-
@_paperclip_attachments[name] ||= ::Paperclip::Attachment.new(name, self, self.class.attachment_definitions[name]).tap do |a|
|
94
|
-
a.post_processing = false if self.class.attachment_definitions[name][:delayed]
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
88
|
def prepare_enqueueing_for name
|
89
|
+
if self.attributes.has_key? "#{name}_processing"
|
90
|
+
write_attribute("#{name}_processing", true)
|
91
|
+
@_enqued_for_processing_with_processing ||= []
|
92
|
+
@_enqued_for_processing_with_processing << name
|
93
|
+
end
|
99
94
|
@_enqued_for_processing ||= []
|
100
95
|
@_enqued_for_processing << name
|
101
96
|
end
|
102
97
|
|
103
98
|
end
|
104
99
|
end
|
105
|
-
|
106
|
-
module Paperclip
|
107
|
-
class Attachment
|
108
|
-
attr_accessor :job_is_processing
|
109
|
-
|
110
|
-
def save_with_prepare_enqueueing
|
111
|
-
was_dirty = @dirty
|
112
|
-
save_without_prepare_enqueueing.tap do
|
113
|
-
if delay_processing? && was_dirty
|
114
|
-
instance.prepare_enqueueing_for name
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
alias_method_chain :save, :prepare_enqueueing
|
119
|
-
|
120
|
-
def url_with_processed style = default_style, include_updated_timestamp = @use_timestamp
|
121
|
-
return url_without_processed style, include_updated_timestamp if job_is_processing
|
122
|
-
|
123
|
-
if !@instance.respond_to?(:"#{name}_processing?")
|
124
|
-
url_without_processed style, include_updated_timestamp
|
125
|
-
else
|
126
|
-
if !processing?
|
127
|
-
url_without_processed style, include_updated_timestamp
|
128
|
-
else
|
129
|
-
if dirty?
|
130
|
-
url_without_processed style, include_updated_timestamp
|
131
|
-
else
|
132
|
-
interpolate(@default_url, style)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
alias_method_chain :url, :processed
|
138
|
-
|
139
|
-
def delay_processing?
|
140
|
-
!!@instance.class.attachment_definitions[@name][:delayed]
|
141
|
-
end
|
142
|
-
|
143
|
-
def processing?
|
144
|
-
@instance.send(:"#{@name}_processing?")
|
145
|
-
end
|
146
|
-
|
147
|
-
def process_delayed!
|
148
|
-
job_is_processing = true
|
149
|
-
reprocess!
|
150
|
-
job_is_processing = false
|
151
|
-
instance.update_attribute("#{name}_processing", false) if instance.attributes.has_key? "#{name}_processing"
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
|
158
|
-
if Object.const_defined?("ActiveRecord")
|
159
|
-
ActiveRecord::Base.send(:include, DelayedPaperclip)
|
160
|
-
end
|
data/rails/init.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
require 'delayed_paperclip'
|
1
|
+
require 'delayed_paperclip/railtie'
|
2
|
+
DelayedPaperclip::Railtie.insert
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module BaseDelayedPaperclipTest
|
2
|
+
def setup
|
3
|
+
super
|
4
|
+
DelayedPaperclip.options[:url_with_processing] = true
|
5
|
+
reset_dummy
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_normal_paperclip_functioning
|
9
|
+
reset_dummy :with_processed => false
|
10
|
+
Paperclip::Attachment.any_instance.expects(:post_process)
|
11
|
+
dummy = Dummy.new(:image => File.open("#{ROOT}/test/fixtures/12k.png"))
|
12
|
+
assert !dummy.image.delay_processing?
|
13
|
+
assert dummy.image.post_processing
|
14
|
+
assert dummy.save
|
15
|
+
assert File.exists?(dummy.image.path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_normal_explisit_post_processing_with_delayed_paperclip
|
19
|
+
reset_dummy :with_processed => true
|
20
|
+
dummy = Dummy.new(:image => File.open("#{ROOT}/test/fixtures/12k.png"))
|
21
|
+
dummy.image.post_processing = true
|
22
|
+
assert !dummy.image.delay_processing?
|
23
|
+
assert dummy.image.post_processing, "Post processing should return true"
|
24
|
+
assert dummy.save
|
25
|
+
assert File.exists?(dummy.image.path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_delayed_paperclip_functioning
|
29
|
+
build_dummy_table(false)
|
30
|
+
reset_class "Dummy", :with_processed => true
|
31
|
+
Paperclip::Attachment.any_instance.expects(:post_process).never
|
32
|
+
dummy = Dummy.new(:image => File.open("#{ROOT}/test/fixtures/12k.png"))
|
33
|
+
assert dummy.image.delay_processing?
|
34
|
+
assert !dummy.image.post_processing
|
35
|
+
assert dummy.save
|
36
|
+
assert File.exists?(dummy.image.path), "Path #{dummy.image.path} should exist"
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_enqueue_job_if_source_changed
|
40
|
+
dummy = Dummy.new(:image => File.open("#{ROOT}/test/fixtures/12k.png"))
|
41
|
+
dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
42
|
+
original_job_count = jobs_count
|
43
|
+
dummy.save
|
44
|
+
assert_equal original_job_count + 1, jobs_count
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_processing_column_kept_intact
|
48
|
+
Paperclip::Attachment.any_instance.stubs(:reprocess!).raises(StandardError.new('oops'))
|
49
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
50
|
+
dummy.save!
|
51
|
+
assert dummy.image_processing?
|
52
|
+
process_jobs
|
53
|
+
assert dummy.image_processing?
|
54
|
+
assert dummy.reload.image_processing?
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_processing_true_when_new_image_added
|
58
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
59
|
+
assert !dummy.image_processing?
|
60
|
+
assert dummy.new_record?
|
61
|
+
dummy.save!
|
62
|
+
assert dummy.reload.image_processing?
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_processed_true_when_delayed_jobs_completed
|
66
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
67
|
+
dummy.save!
|
68
|
+
process_jobs
|
69
|
+
dummy.reload
|
70
|
+
assert !dummy.image_processing?, "Image should no longer be processing"
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_unprocessed_image_returns_missing_url
|
74
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
75
|
+
dummy.save!
|
76
|
+
assert_equal "/images/original/missing.png", dummy.image.url
|
77
|
+
process_jobs
|
78
|
+
dummy.reload
|
79
|
+
assert_match /\/system\/images\/1\/original\/12k.png/, dummy.image.url
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_unprocessed_image_not_returning_missing_url_if_turrned_of_globally
|
83
|
+
DelayedPaperclip.options[:url_with_processing] = false
|
84
|
+
reset_dummy :with_processed => false
|
85
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
86
|
+
dummy.save!
|
87
|
+
assert_match /\/system\/images\/1\/original\/12k.png/, dummy.image.url
|
88
|
+
process_jobs
|
89
|
+
dummy.reload
|
90
|
+
assert_match /\/system\/images\/1\/original\/12k.png/, dummy.image.url
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_unprocessed_image_not_returning_missing_url_if_turrned_of_on_instance
|
94
|
+
reset_dummy :with_processed => false, :url_with_processing => false
|
95
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
96
|
+
dummy.save!
|
97
|
+
assert_match(/\/system\/images\/1\/original\/12k.png/, dummy.image.url)
|
98
|
+
process_jobs
|
99
|
+
dummy.reload
|
100
|
+
assert_match(/\/system\/images\/1\/original\/12k.png/, dummy.image.url)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_original_url_when_no_processing_column
|
104
|
+
reset_dummy :with_processed => false
|
105
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
106
|
+
dummy.save!
|
107
|
+
assert_match(/\/system\/images\/1\/original\/12k.png/, dummy.image.url)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_original_url_if_image_changed
|
111
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
112
|
+
dummy.save!
|
113
|
+
dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
114
|
+
dummy.save!
|
115
|
+
assert_equal '/images/original/missing.png', dummy.image.url
|
116
|
+
process_jobs
|
117
|
+
assert_match(/system\/images\/.*original.*/, dummy.reload.image.url)
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_missing_url_if_image_hasnt_changed
|
121
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
122
|
+
dummy.save!
|
123
|
+
assert_match(/images\/.*missing.*/, dummy.image.url)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_should_not_blow_up_if_dsl_unused
|
127
|
+
reset_dummy :with_processed => false
|
128
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
129
|
+
assert dummy.image.url
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_after_callback_is_functional
|
133
|
+
Dummy.send(:define_method, :done_processing) { puts 'done' }
|
134
|
+
Dummy.after_image_post_process :done_processing
|
135
|
+
Dummy.any_instance.expects(:done_processing)
|
136
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
137
|
+
dummy.save!
|
138
|
+
process_jobs
|
139
|
+
end
|
140
|
+
end
|
@@ -1,137 +1,46 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'base_delayed_paperclip_test'
|
2
3
|
require 'delayed_job'
|
4
|
+
|
3
5
|
Delayed::Worker.backend = :active_record
|
4
6
|
|
5
7
|
class DelayedPaperclipTest < Test::Unit::TestCase
|
8
|
+
include BaseDelayedPaperclipTest
|
9
|
+
|
6
10
|
def setup
|
7
11
|
super
|
8
|
-
|
12
|
+
DelayedPaperclip.options[:background_job_class] = DelayedPaperclip::Jobs::DelayedJob
|
9
13
|
build_delayed_jobs
|
10
|
-
reset_dummy
|
11
14
|
end
|
12
15
|
|
13
|
-
def
|
14
|
-
|
15
|
-
reset_class "Dummy", false
|
16
|
-
|
17
|
-
Paperclip::Attachment.any_instance.expects(:post_process)
|
18
|
-
|
19
|
-
dummy = Dummy.new(:image => File.open("#{ROOT}/test/fixtures/12k.png"))
|
20
|
-
|
21
|
-
assert !dummy.image.delay_processing?
|
22
|
-
assert dummy.image.post_processing
|
23
|
-
assert dummy.save
|
24
|
-
assert File.exists?(dummy.image.path)
|
16
|
+
def process_jobs
|
17
|
+
Delayed::Worker.new.work_off
|
25
18
|
end
|
26
19
|
|
27
|
-
def
|
28
|
-
|
29
|
-
reset_class "Dummy", true
|
30
|
-
|
31
|
-
Paperclip::Attachment.any_instance.expects(:post_process).never
|
32
|
-
|
33
|
-
dummy = Dummy.new(:image => File.open("#{ROOT}/test/fixtures/12k.png"))
|
34
|
-
|
35
|
-
assert dummy.image.delay_processing?
|
36
|
-
assert !dummy.image.post_processing
|
37
|
-
assert dummy.save
|
38
|
-
assert File.exists?(dummy.image.path)
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
def test_enqueue_job_if_source_changed
|
43
|
-
@dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
44
|
-
|
45
|
-
original_job_count = Delayed::Job.count
|
46
|
-
@dummy.save
|
47
|
-
|
48
|
-
assert_equal original_job_count + 1, Delayed::Job.count
|
20
|
+
def jobs_count
|
21
|
+
Delayed::Job.count
|
49
22
|
end
|
50
23
|
|
51
24
|
def test_perform_job
|
52
|
-
|
25
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
26
|
+
dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
53
27
|
Paperclip::Attachment.any_instance.expects(:reprocess!)
|
54
|
-
|
55
|
-
@dummy.save!
|
28
|
+
dummy.save!
|
56
29
|
Delayed::Job.last.payload_object.perform
|
57
30
|
end
|
58
31
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
@dummy_class.send(:define_method, :done_processing) { puts 'done' }
|
72
|
-
@dummy_class.after_image_post_process :done_processing
|
73
|
-
Dummy.any_instance.expects(:done_processing)
|
74
|
-
|
75
|
-
@dummy.save!
|
76
|
-
DelayedPaperclip::Jobs::DelayedJob.new(@dummy.class.name, @dummy.id, :image).perform
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_processing_true_when_new_image_added
|
80
|
-
@dummy = reset_dummy(true)
|
81
|
-
|
82
|
-
assert !@dummy.image_processing?
|
83
|
-
assert @dummy.new_record?
|
84
|
-
@dummy.save!
|
85
|
-
assert @dummy.reload.image_processing?
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_processed_true_when_delayed_jobs_completed
|
89
|
-
@dummy = reset_dummy(true)
|
90
|
-
@dummy.save!
|
91
|
-
|
92
|
-
Delayed::Worker.new.work_off
|
93
|
-
|
94
|
-
@dummy.reload
|
95
|
-
assert !@dummy.image_processing?
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_unprocessed_image_returns_missing_url
|
99
|
-
@dummy = reset_dummy(true)
|
100
|
-
@dummy.save!
|
101
|
-
|
102
|
-
assert_equal "/images/original/missing.png", @dummy.image.url
|
103
|
-
|
104
|
-
Delayed::Job.first.invoke_job
|
105
|
-
|
106
|
-
@dummy.reload
|
107
|
-
assert_match(/\/system\/images\/1\/original\/12k.png/, @dummy.image.url)
|
32
|
+
def build_delayed_jobs
|
33
|
+
ActiveRecord::Base.connection.create_table :delayed_jobs, :force => true do |table|
|
34
|
+
table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
|
35
|
+
table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
|
36
|
+
table.text :handler # YAML-encoded string of the object that will do work
|
37
|
+
table.string :last_error # reason for last failure (See Note below)
|
38
|
+
table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
|
39
|
+
table.datetime :locked_at # Set when a client is working on this object
|
40
|
+
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
41
|
+
table.string :locked_by # Who is working on this object (if locked)
|
42
|
+
table.timestamps
|
43
|
+
end
|
108
44
|
end
|
109
45
|
|
110
|
-
def test_original_url_when_no_processing_column
|
111
|
-
@dummy = reset_dummy(false)
|
112
|
-
@dummy.save!
|
113
|
-
|
114
|
-
assert_match(/\/system\/images\/1\/original\/12k.png/, @dummy.image.url)
|
115
|
-
end
|
116
|
-
|
117
|
-
def test_original_url_if_image_changed
|
118
|
-
@dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
119
|
-
@dummy.save!
|
120
|
-
|
121
|
-
assert_match(/system\/images\/.*original.*/, @dummy.image.url)
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_missing_url_if_image_hasnt_changed
|
125
|
-
@dummy = reset_dummy(true)
|
126
|
-
@dummy.save!
|
127
|
-
|
128
|
-
assert_match(/images\/.*missing.*/, @dummy.image.url)
|
129
|
-
end
|
130
|
-
|
131
|
-
def test_should_not_blow_up_if_dsl_unused
|
132
|
-
reset_class "Dummy", false
|
133
|
-
@dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
134
|
-
|
135
|
-
assert @dummy.image.url
|
136
|
-
end
|
137
46
|
end
|
@@ -1,54 +1,32 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
|
2
|
+
require 'base_delayed_paperclip_test'
|
3
3
|
require 'resque'
|
4
4
|
|
5
5
|
class ResquePaperclipTest < Test::Unit::TestCase
|
6
|
+
include BaseDelayedPaperclipTest
|
7
|
+
|
6
8
|
def setup
|
7
9
|
super
|
8
|
-
|
9
10
|
# Make sure that we just test Resque in here
|
10
|
-
|
11
|
-
|
11
|
+
DelayedPaperclip.options[:background_job_class] = DelayedPaperclip::Jobs::Resque
|
12
12
|
Resque.remove_queue(:paperclip)
|
13
|
-
reset_dummy
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@dummy.save
|
15
|
+
def process_jobs
|
16
|
+
worker = Resque::Worker.new(:paperclip)
|
17
|
+
worker.process
|
18
|
+
end
|
21
19
|
|
22
|
-
|
20
|
+
def jobs_count
|
21
|
+
Resque.size(:paperclip)
|
23
22
|
end
|
24
23
|
|
25
24
|
def test_perform_job
|
25
|
+
dummy = Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
26
|
+
dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
26
27
|
Paperclip::Attachment.any_instance.expects(:reprocess!)
|
27
|
-
|
28
|
-
DelayedPaperclip::Jobs::Resque.perform(
|
28
|
+
dummy.save!
|
29
|
+
DelayedPaperclip::Jobs::Resque.perform(dummy.class.name, dummy.id, :image)
|
29
30
|
end
|
30
31
|
|
31
|
-
def test_after_callback_is_functional
|
32
|
-
@dummy_class.send(:define_method, :done_processing) { puts 'done' }
|
33
|
-
@dummy_class.after_image_post_process :done_processing
|
34
|
-
Dummy.any_instance.expects(:done_processing)
|
35
|
-
|
36
|
-
@dummy.save!
|
37
|
-
DelayedPaperclip::Jobs::Resque.perform(@dummy.class.name, @dummy.id, :image)
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_processing_column_kept_intact
|
41
|
-
@dummy = reset_dummy(true)
|
42
|
-
|
43
|
-
@dummy.image = File.open("#{RAILS_ROOT}/test/fixtures/12k.png")
|
44
|
-
Paperclip::Attachment.any_instance.stubs(:reprocess!).raises(StandardError.new('oops'))
|
45
|
-
|
46
|
-
@dummy.save!
|
47
|
-
assert @dummy.image_processing?, "image should be processing #{@dummy.inspect}"
|
48
|
-
|
49
|
-
worker = Resque::Worker.new(:paperclip)
|
50
|
-
worker.process
|
51
|
-
|
52
|
-
assert @dummy.reload.image_processing?, "image should be processing"
|
53
|
-
end
|
54
32
|
end
|
data/test/test_helper.rb
CHANGED
@@ -11,7 +11,8 @@ ROOT = File.join(File.dirname(__FILE__), '..')
|
|
11
11
|
RAILS_ROOT = ROOT
|
12
12
|
$LOAD_PATH << File.join(ROOT, 'lib')
|
13
13
|
|
14
|
-
require 'delayed_paperclip'
|
14
|
+
require 'delayed_paperclip/railtie'
|
15
|
+
DelayedPaperclip::Railtie.insert
|
15
16
|
|
16
17
|
class Test::Unit::TestCase
|
17
18
|
def setup
|
@@ -25,46 +26,38 @@ FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
|
|
25
26
|
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
26
27
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
27
28
|
ActiveRecord::Base.establish_connection(config['test'])
|
29
|
+
Paperclip.logger = ActiveRecord::Base.logger
|
28
30
|
|
29
|
-
def reset_dummy(
|
30
|
-
|
31
|
+
# def reset_dummy(options = {})
|
32
|
+
# reset_dummy(options)
|
33
|
+
# Dummy.new(:image => File.open("#{RAILS_ROOT}/test/fixtures/12k.png"))
|
34
|
+
# end
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def reset_class class_name, include_process = true
|
38
|
-
Object.send(:remove_const, class_name) rescue nil
|
39
|
-
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
|
40
|
-
klass.class_eval do
|
41
|
-
has_attached_file :image
|
42
|
-
process_in_background :image if include_process
|
43
|
-
end
|
44
|
-
@dummy_class = klass
|
36
|
+
def reset_dummy(options = {})
|
37
|
+
options[:with_processed] = true unless options.key?(:with_processed)
|
38
|
+
build_dummy_table(options[:with_processed])
|
39
|
+
reset_class("Dummy", options)
|
45
40
|
end
|
46
41
|
|
47
42
|
def build_dummy_table(with_processed)
|
48
|
-
ActiveRecord::Base.connection.create_table :dummies,
|
43
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |t|
|
49
44
|
t.string :image_file_name
|
50
45
|
t.string :image_content_type
|
51
46
|
t.integer :image_file_size
|
52
47
|
t.datetime :image_updated_at
|
53
|
-
|
54
48
|
t.boolean(:image_processing, :default => false) if with_processed
|
55
49
|
end
|
56
50
|
end
|
57
51
|
|
58
|
-
def
|
59
|
-
ActiveRecord::Base.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
67
|
-
table.string :locked_by # Who is working on this object (if locked)
|
68
|
-
table.timestamps
|
52
|
+
def reset_class(class_name, options)
|
53
|
+
ActiveRecord::Base.send(:include, Paperclip::Glue)
|
54
|
+
Object.send(:remove_const, class_name) rescue nil
|
55
|
+
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
|
56
|
+
klass.class_eval do
|
57
|
+
include Paperclip::Glue
|
58
|
+
has_attached_file :image
|
59
|
+
process_in_background :image, options if options[:with_processed]
|
69
60
|
end
|
61
|
+
klass.reset_column_information
|
62
|
+
klass
|
70
63
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_paperclip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.4.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,23 +10,22 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-
|
14
|
-
default_executable:
|
13
|
+
date: 2011-11-12 00:00:00.000000000Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: paperclip
|
18
|
-
requirement: &
|
17
|
+
requirement: &2153012620 !ruby/object:Gem::Requirement
|
19
18
|
none: false
|
20
19
|
requirements:
|
21
|
-
- -
|
20
|
+
- - ! '>='
|
22
21
|
- !ruby/object:Gem::Version
|
23
|
-
version: 2.
|
22
|
+
version: 2.4.0
|
24
23
|
type: :runtime
|
25
24
|
prerelease: false
|
26
|
-
version_requirements: *
|
25
|
+
version_requirements: *2153012620
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
27
|
name: mocha
|
29
|
-
requirement: &
|
28
|
+
requirement: &2153012200 !ruby/object:Gem::Requirement
|
30
29
|
none: false
|
31
30
|
requirements:
|
32
31
|
- - ! '>='
|
@@ -34,10 +33,10 @@ dependencies:
|
|
34
33
|
version: '0'
|
35
34
|
type: :development
|
36
35
|
prerelease: false
|
37
|
-
version_requirements: *
|
36
|
+
version_requirements: *2153012200
|
38
37
|
- !ruby/object:Gem::Dependency
|
39
|
-
name: sqlite3
|
40
|
-
requirement: &
|
38
|
+
name: sqlite3
|
39
|
+
requirement: &2153011700 !ruby/object:Gem::Requirement
|
41
40
|
none: false
|
42
41
|
requirements:
|
43
42
|
- - ! '>='
|
@@ -45,10 +44,10 @@ dependencies:
|
|
45
44
|
version: '0'
|
46
45
|
type: :development
|
47
46
|
prerelease: false
|
48
|
-
version_requirements: *
|
47
|
+
version_requirements: *2153011700
|
49
48
|
- !ruby/object:Gem::Dependency
|
50
49
|
name: delayed_job
|
51
|
-
requirement: &
|
50
|
+
requirement: &2153011200 !ruby/object:Gem::Requirement
|
52
51
|
none: false
|
53
52
|
requirements:
|
54
53
|
- - ! '>='
|
@@ -56,10 +55,10 @@ dependencies:
|
|
56
55
|
version: '0'
|
57
56
|
type: :development
|
58
57
|
prerelease: false
|
59
|
-
version_requirements: *
|
58
|
+
version_requirements: *2153011200
|
60
59
|
- !ruby/object:Gem::Dependency
|
61
60
|
name: resque
|
62
|
-
requirement: &
|
61
|
+
requirement: &2153010740 !ruby/object:Gem::Requirement
|
63
62
|
none: false
|
64
63
|
requirements:
|
65
64
|
- - ! '>='
|
@@ -67,7 +66,7 @@ dependencies:
|
|
67
66
|
version: '0'
|
68
67
|
type: :development
|
69
68
|
prerelease: false
|
70
|
-
version_requirements: *
|
69
|
+
version_requirements: *2153010740
|
71
70
|
description: Process your Paperclip attachments in the background with delayed_job,
|
72
71
|
Resque or your own processor.
|
73
72
|
email: jesse@jstorimer.com
|
@@ -75,24 +74,23 @@ executables: []
|
|
75
74
|
extensions: []
|
76
75
|
extra_rdoc_files: []
|
77
76
|
files:
|
78
|
-
- .gitignore
|
79
|
-
- .rvmrc
|
80
|
-
- CONTRIBUTING
|
81
|
-
- Gemfile
|
82
|
-
- LICENSE
|
83
77
|
- README.textile
|
78
|
+
- LICENSE
|
84
79
|
- Rakefile
|
85
|
-
-
|
86
|
-
- lib/delayed_paperclip.rb
|
80
|
+
- init.rb
|
81
|
+
- lib/delayed_paperclip/attachment.rb
|
87
82
|
- lib/delayed_paperclip/jobs/delayed_job.rb
|
88
83
|
- lib/delayed_paperclip/jobs/resque.rb
|
89
|
-
-
|
84
|
+
- lib/delayed_paperclip/jobs.rb
|
85
|
+
- lib/delayed_paperclip/railtie.rb
|
86
|
+
- lib/delayed_paperclip.rb
|
87
|
+
- test/base_delayed_paperclip_test.rb
|
90
88
|
- test/database.yml
|
91
89
|
- test/delayed_paperclip_test.rb
|
92
90
|
- test/fixtures/12k.png
|
93
91
|
- test/resque_paperclip_test.rb
|
94
92
|
- test/test_helper.rb
|
95
|
-
|
93
|
+
- rails/init.rb
|
96
94
|
homepage: http://github.com/jstorimer/delayed_paperclip
|
97
95
|
licenses: []
|
98
96
|
post_install_message:
|
@@ -113,13 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
111
|
version: '0'
|
114
112
|
requirements: []
|
115
113
|
rubyforge_project:
|
116
|
-
rubygems_version: 1.
|
114
|
+
rubygems_version: 1.8.10
|
117
115
|
signing_key:
|
118
116
|
specification_version: 3
|
119
117
|
summary: Process your Paperclip attachments in the background.
|
120
|
-
test_files:
|
121
|
-
- test/database.yml
|
122
|
-
- test/delayed_paperclip_test.rb
|
123
|
-
- test/fixtures/12k.png
|
124
|
-
- test/resque_paperclip_test.rb
|
125
|
-
- test/test_helper.rb
|
118
|
+
test_files: []
|
data/.gitignore
DELETED
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm gemset use delayed_paperclip --create
|
data/CONTRIBUTING
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
Contributor Policy
|
2
|
-
=================
|
3
|
-
|
4
|
-
Commit bit. If you have a commit accepted into the project then you get full git access to the repo. If I don't give you this in a timely manner just send me a message.
|
5
|
-
|
6
|
-
Testing
|
7
|
-
======
|
8
|
-
|
9
|
-
Please don't commit code without tests. You can bootstrap the development environment by running `bundle install`. After that, running `rake test` should just work. If it doesn't then file a bug.
|
10
|
-
|
11
|
-
Versioning
|
12
|
-
=========
|
13
|
-
|
14
|
-
Don't bump the version in any changes you make or pull in to the project. I'll maintain rights to push the gem to rubygems.org and make releases when appropriate.
|
15
|
-
|
16
|
-
And please keep the README up to date. Thank you!
|
data/Gemfile
DELETED
data/delayed_paperclip.gemspec
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.name = %q{delayed_paperclip}
|
3
|
-
s.version = "0.7.2"
|
4
|
-
|
5
|
-
s.authors = ["Jesse Storimer", "Bert Goethals"]
|
6
|
-
s.summary = %q{Process your Paperclip attachments in the background.}
|
7
|
-
s.description = %q{Process your Paperclip attachments in the background with delayed_job, Resque or your own processor.}
|
8
|
-
s.email = %q{jesse@jstorimer.com}
|
9
|
-
s.homepage = %q{http://github.com/jstorimer/delayed_paperclip}
|
10
|
-
|
11
|
-
s.files = `git ls-files`.split("\n")
|
12
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
13
|
-
|
14
|
-
s.add_runtime_dependency 'paperclip', ["~> 2.3.0"]
|
15
|
-
|
16
|
-
s.add_development_dependency 'mocha'
|
17
|
-
s.add_development_dependency 'sqlite3-ruby'
|
18
|
-
s.add_development_dependency 'delayed_job'
|
19
|
-
s.add_development_dependency 'resque'
|
20
|
-
end
|
21
|
-
|