/
mounter.rb
178 lines (152 loc) · 4.41 KB
/
mounter.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
module CarrierWave
# this is an internal class, used by CarrierWave::Mount so that
# we don't pollute the model with a lot of methods.
class Mounter #:nodoc:
attr_reader :column, :record, :remote_urls, :integrity_errors,
:processing_errors, :download_errors
attr_accessor :remove, :remote_request_headers
def initialize(record, column, options={})
@record = record
@column = column
@options = record.class.uploader_options[column]
@download_errors = []
@processing_errors = []
@integrity_errors = []
end
def uploader_class
record.class.uploaders[column]
end
def blank_uploader
uploader_class.new(record, column)
end
def identifiers
uploaders.map(&:identifier)
end
def read_identifiers
[record.read_uploader(serialization_column)].flatten.reject(&:blank?)
end
def uploaders
@uploaders ||= read_identifiers.map do |identifier|
uploader = blank_uploader
uploader.retrieve_from_store!(identifier) if identifier.present?
uploader
end
end
def cache(new_files)
return if !new_files.is_a?(Array) && new_files.blank?
old_uploaders = uploaders
@uploaders = new_files.map do |new_file|
handle_error do
if new_file.is_a?(String)
uploader = old_uploaders.detect { |uploader| uploader.identifier == new_file }
uploader.staged = true if uploader
uploader
else
uploader = blank_uploader
uploader.cache!(new_file)
uploader
end
end
end.compact
end
def cache_names
uploaders.map(&:cache_name).compact
end
def cache_names=(cache_names)
return if cache_names.blank?
clear_unstaged
cache_names.map do |cache_name|
begin
uploader = blank_uploader
uploader.retrieve_from_cache!(cache_name)
@uploaders << uploader
rescue CarrierWave::InvalidParameter
# ignore
end
end
end
def remote_urls=(urls)
return if urls.blank? || urls.all?(&:blank?)
@remote_urls = urls
clear_unstaged
urls.zip(remote_request_headers || []).map do |url, header|
handle_error do
uploader = blank_uploader
uploader.download!(url, header || {})
@uploaders << uploader
end
end
end
def store!
if remove?
remove!
else
uploaders.reject(&:blank?).each(&:store!)
end
end
def urls(*args)
uploaders.map { |u| u.url(*args) }
end
def blank?
uploaders.none?(&:present?)
end
def remove?
remove.present? && remove !~ /\A0|false$\z/
end
def remove!
uploaders.reject(&:blank?).each(&:remove!)
@uploaders = []
end
def serialization_column
option(:mount_on) || column
end
def remove_previous(before=nil, after=nil)
after ||= []
return unless before
# both 'before' and 'after' can be string when 'mount_on' option is set
before = before.reject(&:blank?).map do |value|
if value.is_a?(String)
uploader = blank_uploader
uploader.retrieve_from_store!(value)
uploader
else
value
end
end
after_paths = after.reject(&:blank?).map do |value|
if value.is_a?(String)
uploader = blank_uploader
uploader.retrieve_from_store!(value)
uploader
else
value
end.path
end
before.each do |uploader|
uploader.remove! if uploader.remove_previously_stored_files_after_update && !after_paths.include?(uploader.path)
end
end
attr_accessor :uploader_options
private
def option(name)
self.uploader_options ||= {}
self.uploader_options[name] ||= record.class.uploader_option(column, name)
end
def clear_unstaged
@uploaders ||= []
@uploaders.keep_if(&:staged)
end
def handle_error
yield
rescue CarrierWave::DownloadError => e
@download_errors << e
raise e unless option(:ignore_download_errors)
rescue CarrierWave::ProcessingError => e
@processing_errors << e
raise e unless option(:ignore_processing_errors)
rescue CarrierWave::IntegrityError => e
@integrity_errors << e
raise e unless option(:ignore_integrity_errors)
end
end # Mounter
end # CarrierWave