forked from jstorimer/delayed_paperclip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
delayed_paperclip.rb
159 lines (128 loc) · 4.47 KB
/
delayed_paperclip.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
require 'paperclip'
require 'delayed_paperclip'
require 'delayed_paperclip/jobs/delayed_job'
require 'delayed_paperclip/jobs/resque'
module DelayedPaperclip
class << self
def options
@options ||= {
:background_job_class => detect_background_task
}
end
def detect_background_task
return DelayedPaperclip::Jobs::DelayedJob if defined? ::Delayed::Job
return DelayedPaperclip::Jobs::Resque if defined? ::Resque
end
def processor
options[:background_job_class]
end
def enqueue(instance_klass, instance_id, attachment_name)
processor.enqueue_delayed_paperclip(instance_klass, instance_id, attachment_name)
end
def process_job(instance_klass, instance_id, attachment_name)
instance_klass.constantize.find(instance_id).
send(attachment_name).
process_delayed!
end
end
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def process_in_background(name, options = {})
include InstanceMethods
attachment_definitions[name][:delayed] = {}
attachment_definitions[name][:delayed][:priority] = options.key?(:priority) ? options[:priority] : 0
if respond_to?(:after_commit)
after_commit :enqueue_delayed_processing
else
after_save :enqueue_delayed_processing
end
end
end
module InstanceMethods
# setting each inididual NAME_processing to true, skipping the ActiveModel dirty setter
# Then immediately push the state to the database
def mark_enqueue_delayed_processing
unless @_enqued_for_processing_with_processing.blank? # catches nil and empy arrays
updates = @_enqued_for_processing_with_processing.collect{|n| "#{n}_processing = :true" }.join(", ")
updates = ActiveRecord::Base.send(:sanitize_sql_array, [updates, {:true => true}])
self.class.update_all(updates, "id = #{self.id}")
end
end
# First mark processing
# then create
def enqueue_delayed_processing
mark_enqueue_delayed_processing
(@_enqued_for_processing || []).each do |name|
enqueue_post_processing_for(name)
end
@_enqued_for_processing_with_processing = []
@_enqued_for_processing = []
end
def enqueue_post_processing_for name
DelayedPaperclip.enqueue(self.class.name, read_attribute(:id), name.to_sym)
end
def attachment_for name
@_paperclip_attachments ||= {}
@_paperclip_attachments[name] ||= ::Paperclip::Attachment.new(name, self, self.class.attachment_definitions[name]).tap do |a|
a.post_processing = false if self.class.attachment_definitions[name][:delayed]
end
end
def prepare_enqueueing_for name
if self.attributes.has_key? "#{name}_processing"
write_attribute("#{name}_processing", true)
@_enqued_for_processing_with_processing ||= []
@_enqued_for_processing_with_processing << name
end
@_enqued_for_processing ||= []
@_enqued_for_processing << name
end
end
end
module Paperclip
class Attachment
attr_accessor :job_is_processing
def save_with_prepare_enqueueing
was_dirty = @dirty
save_without_prepare_enqueueing.tap do
if delay_processing? && was_dirty
instance.prepare_enqueueing_for name
end
end
end
alias_method_chain :save, :prepare_enqueueing
def url_with_processed style = default_style, include_updated_timestamp = @use_timestamp
return url_without_processed style, include_updated_timestamp if job_is_processing
if !@instance.respond_to?(:"#{name}_processing?")
url_without_processed style, include_updated_timestamp
else
if !processing?
url_without_processed style, include_updated_timestamp
else
if dirty?
url_without_processed style, include_updated_timestamp
else
interpolate(@default_url, style)
end
end
end
end
alias_method_chain :url, :processed
def delay_processing?
!!@instance.class.attachment_definitions[@name][:delayed]
end
def processing?
@instance.send(:"#{@name}_processing?")
end
def process_delayed!
job_is_processing = true
reprocess!
job_is_processing = false
instance.update_attribute("#{name}_processing", false) if instance.attributes.has_key? "#{name}_processing"
end
end
end
if Object.const_defined?("ActiveRecord")
ActiveRecord::Base.send(:include, DelayedPaperclip)
end