attachs 4.0.0.2 → 4.0.0.3
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 +4 -4
- data/lib/attachs.rb +2 -0
- data/lib/attachs/attachment.rb +5 -340
- data/lib/attachs/attachment/attributes.rb +118 -0
- data/lib/attachs/attachment/processing.rb +242 -0
- data/lib/attachs/collection.rb +1 -1
- data/lib/attachs/extensions/active_record/validations/attachment_content_type_validator.rb +5 -7
- data/lib/attachs/extensions/active_record/validations/attachment_presence_validator.rb +5 -6
- data/lib/attachs/extensions/active_record/validations/attachment_size_validator.rb +4 -5
- data/lib/attachs/extensions/active_record/validations/attachment_validator.rb +11 -3
- data/lib/attachs/locales/en.yml +1 -1
- data/lib/attachs/locales/es.yml +1 -1
- data/lib/attachs/version.rb +1 -1
- data/lib/generators/attachs/upload/templates/model.rb +4 -3
- data/test/dummy/app/models/upload.rb +5 -4
- data/test/dummy/log/test.log +4699 -0
- data/test/{validator_test.rb → validation_test.rb} +44 -28
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c16c8226d22e2d772ba2f3ee5aa32f5e9b0b18e0
|
4
|
+
data.tar.gz: aa8c1e0487680a41a7a97ac4ed9d0426948e3fb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0fa01842ed7f65ec104a4aed5cafa51427c432d319797b7048601ce20f7617657c0f32dafecef870bc7501a22958375c908a2039c30019922e147174ffab912
|
7
|
+
data.tar.gz: f841b2bb5bc391a640d6a46fe11232277b8cac77f66715007f2e105602a7ba00c0875fe527ec07a01498c561e61c8cd4298b53c682eadc82ec80662f05679ffb
|
data/lib/attachs.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'attachs/attachment/attributes'
|
2
|
+
require 'attachs/attachment/processing'
|
1
3
|
require 'attachs/extensions/active_record/validations/attachment_validator'
|
2
4
|
require 'attachs/extensions/active_record/validations/attachment_content_type_validator'
|
3
5
|
require 'attachs/extensions/active_record/validations/attachment_presence_validator'
|
data/lib/attachs/attachment.rb
CHANGED
@@ -1,344 +1,9 @@
|
|
1
1
|
module Attachs
|
2
2
|
class Attachment
|
3
|
-
include
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@record = record
|
9
|
-
@record_attribute = record_attribute
|
10
|
-
@options = options
|
11
|
-
@original_attributes = @attributes = normalize_attributes(attributes)
|
12
|
-
end
|
13
|
-
|
14
|
-
%i(id size filename content_type uploaded_at).each do |name|
|
15
|
-
define_method name do
|
16
|
-
attributes[name]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def basename
|
21
|
-
if filename
|
22
|
-
File.basename filename, extension
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def extension
|
27
|
-
if filename
|
28
|
-
File.extname filename
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def present?
|
33
|
-
filename.present? && content_type.present? && size.present?
|
34
|
-
end
|
35
|
-
|
36
|
-
def blank?
|
37
|
-
!present?
|
38
|
-
end
|
39
|
-
|
40
|
-
def persisted?
|
41
|
-
record.persisted? && paths.any? && uploaded_at
|
42
|
-
end
|
43
|
-
|
44
|
-
def changed?
|
45
|
-
@original_attributes != @attributes
|
46
|
-
end
|
47
|
-
|
48
|
-
def type
|
49
|
-
if content_type
|
50
|
-
if content_type.starts_with?('image/')
|
51
|
-
'image'
|
52
|
-
else
|
53
|
-
'file'
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def url(style=:original)
|
59
|
-
paths = attributes[:paths]
|
60
|
-
if paths.has_key?(style)
|
61
|
-
storage.url paths[style]
|
62
|
-
elsif options.has_key?(:default_path)
|
63
|
-
template = options[:default_path]
|
64
|
-
path = generate_path(template, style)
|
65
|
-
storage.url path
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def position
|
70
|
-
if options[:multiple]
|
71
|
-
attributes[:position]
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def position=(value)
|
76
|
-
if options[:multiple]
|
77
|
-
attributes[:position] = value
|
78
|
-
write_record
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def assign(value)
|
83
|
-
source, new_attributes = process_value(value)
|
84
|
-
if new_attributes
|
85
|
-
unless changed?
|
86
|
-
@original_attributes = attributes
|
87
|
-
end
|
88
|
-
@attributes = new_attributes
|
89
|
-
write_record
|
90
|
-
@source = source
|
91
|
-
@value = value
|
92
|
-
end
|
93
|
-
end
|
94
|
-
alias_method :value=, :assign
|
95
|
-
|
96
|
-
def _destroy=(value)
|
97
|
-
if ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
|
98
|
-
assign nil
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def save
|
103
|
-
if changed?
|
104
|
-
if original_attributes[:paths].any? || original_attributes[:old_paths].any?
|
105
|
-
Jobs::DeleteJob.perform_later(
|
106
|
-
original_attributes[:paths].values +
|
107
|
-
original_attributes[:old_paths]
|
108
|
-
)
|
109
|
-
end
|
110
|
-
case source.class.name
|
111
|
-
when 'Attachs::Attachment'
|
112
|
-
file = storage.get(source.paths[:original])
|
113
|
-
storage.process file, paths, styles
|
114
|
-
when 'Upload'
|
115
|
-
source.file.paths.each do |style, path|
|
116
|
-
storage.copy path, paths[style]
|
117
|
-
end
|
118
|
-
when 'ActionDispatch::Http::UploadedFile'
|
119
|
-
storage.process source, paths, styles
|
120
|
-
end
|
121
|
-
@source = @value = nil
|
122
|
-
@original_attributes = @attributes
|
123
|
-
elsif present?
|
124
|
-
if paths != generate_paths
|
125
|
-
Jobs::UpdateJob.perform_later record, record_attribute.to_s
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def update_paths
|
131
|
-
if changed?
|
132
|
-
raise 'Save attachment before update paths'
|
133
|
-
else
|
134
|
-
new_paths = generate_paths
|
135
|
-
if paths != new_paths
|
136
|
-
new_paths.each do |style, new_path|
|
137
|
-
original_path = paths[style]
|
138
|
-
if original_path != new_path
|
139
|
-
unless storage.exists?(new_path)
|
140
|
-
storage.copy original_path, new_path
|
141
|
-
end
|
142
|
-
attributes[:paths][style] = new_path
|
143
|
-
attributes[:old_paths] |= [original_path]
|
144
|
-
end
|
145
|
-
end
|
146
|
-
update_record
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def reprocess
|
152
|
-
if changed?
|
153
|
-
raise 'Save attachment before reprocess'
|
154
|
-
elsif present? && styles
|
155
|
-
file = storage.get(paths[:original])
|
156
|
-
paths.each do |style, path|
|
157
|
-
if storage.exists?(path)
|
158
|
-
storage.delete path
|
159
|
-
end
|
160
|
-
Rails.logger.info "Regenerating: #{style} => #{path}"
|
161
|
-
end
|
162
|
-
new_paths = generate_paths
|
163
|
-
storage.process file, new_paths, styles
|
164
|
-
attributes[:paths] = new_paths
|
165
|
-
update_record
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def fix_missings
|
170
|
-
if changed?
|
171
|
-
raise 'Save attachment before fix missings'
|
172
|
-
elsif present? && styles
|
173
|
-
missings = paths.slice(:original)
|
174
|
-
paths.except(:original).each do |style, path|
|
175
|
-
unless storage.exists?(path)
|
176
|
-
missings[style] = path
|
177
|
-
Rails.logger.info "Generating: #{style} => #{path}"
|
178
|
-
end
|
179
|
-
end
|
180
|
-
if missings.size > 1
|
181
|
-
file = storage.get(paths[:original])
|
182
|
-
storage.process file, missings, styles
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def destroy
|
188
|
-
assign nil
|
189
|
-
save
|
190
|
-
end
|
191
|
-
|
192
|
-
def method_missing(name, *args, &block)
|
193
|
-
if attributes.has_key?(name)
|
194
|
-
attributes[name]
|
195
|
-
else
|
196
|
-
super
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def respond_to_missing?(name, include_private=false)
|
201
|
-
attributes.has_key?(name) || super
|
202
|
-
end
|
203
|
-
|
204
|
-
def persist
|
205
|
-
if changed? && present?
|
206
|
-
new_paths = generate_paths
|
207
|
-
if paths != new_paths
|
208
|
-
attributes[:paths] = new_paths
|
209
|
-
attributes[:uploaded_at] = Time.now
|
210
|
-
write_record
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def unpersist
|
216
|
-
if changed? && present?
|
217
|
-
attributes[:paths] = original_attributes[:paths]
|
218
|
-
attributes[:uploaded_at] = original_attributes[:uploaded_at]
|
219
|
-
write_record
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def styles
|
224
|
-
case value = options[:styles]
|
225
|
-
when Proc
|
226
|
-
value.call(record) || {}
|
227
|
-
when Hash
|
228
|
-
value
|
229
|
-
else
|
230
|
-
{}
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
private
|
235
|
-
|
236
|
-
def storage
|
237
|
-
Attachs.storage
|
238
|
-
end
|
239
|
-
|
240
|
-
def normalize_attributes(attributes)
|
241
|
-
attributes.reverse_merge(paths: {}, old_paths: []).deep_symbolize_keys
|
242
|
-
end
|
243
|
-
|
244
|
-
def write_record(value=nil)
|
245
|
-
unless record.destroyed?
|
246
|
-
record.send "#{record_attribute}_will_change!"
|
247
|
-
record.send :write_attribute, record_attribute, (value || raw_attributes)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
def raw_attributes
|
252
|
-
if options[:multiple]
|
253
|
-
record.send(:read_attribute, record_attribute).reject{ |h| h['id'] == id }.append attributes
|
254
|
-
else
|
255
|
-
attributes
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def update_record(value=nil)
|
260
|
-
unless record.destroyed?
|
261
|
-
record.update_column record_attribute, (value || raw_attributes)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
def generate_path(template, style)
|
266
|
-
if path = template.try(:dup)
|
267
|
-
path.gsub! ':style', style.to_s.gsub('_', '-')
|
268
|
-
path.scan(/:[a-z_]+/).each do |token|
|
269
|
-
name = token.from(1).to_sym
|
270
|
-
path.gsub! token, interpolate(name).to_s.parameterize
|
271
|
-
end
|
272
|
-
path.squeeze! '-'
|
273
|
-
path.squeeze! '/'
|
274
|
-
path.gsub! '-.', '.'
|
275
|
-
path.gsub! '/-', '/'
|
276
|
-
path.gsub! '-/', '/'
|
277
|
-
path.sub! /^\//, ''
|
278
|
-
path
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
def generate_paths
|
283
|
-
template = options[:path]
|
284
|
-
paths = { original: generate_path(template, :original) }
|
285
|
-
styles.each do |style, geometry|
|
286
|
-
paths[style] = generate_path(template, style)
|
287
|
-
end
|
288
|
-
paths
|
289
|
-
end
|
290
|
-
|
291
|
-
def interpolate(name)
|
292
|
-
if %i(basename extension).include?(name)
|
293
|
-
send name
|
294
|
-
elsif name == :attribute
|
295
|
-
record_attribute
|
296
|
-
elsif attributes.except(:upload_at, :paths, :old_paths).has_key?(name)
|
297
|
-
attributes[name]
|
298
|
-
else
|
299
|
-
Attachs.interpolations.find(name).call record
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
def generate_id
|
304
|
-
SecureRandom.uuid.gsub '-', ''
|
305
|
-
end
|
306
|
-
|
307
|
-
def process_value(value)
|
308
|
-
case value.class.name
|
309
|
-
when 'NilClass'
|
310
|
-
[nil, {}]
|
311
|
-
when 'Attachs::Attachment'
|
312
|
-
[value, value.attributes.merge(id: generate_id)]
|
313
|
-
when 'Upload'
|
314
|
-
[value, value.file.attributes.merge(id: generate_id)]
|
315
|
-
when 'String','Fixnum','Bignum'
|
316
|
-
if Rails.configuration.cache_classes == false
|
317
|
-
Rails.application.eager_load!
|
318
|
-
end
|
319
|
-
if defined?(Upload)
|
320
|
-
upload = Upload.find(value)
|
321
|
-
[upload, upload.file.attributes.merge(id: generate_id)]
|
322
|
-
end
|
323
|
-
when 'ActionDispatch::Http::UploadedFile'
|
324
|
-
attributes = {
|
325
|
-
id: generate_id,
|
326
|
-
filename: value.original_filename,
|
327
|
-
content_type: value.content_type,
|
328
|
-
size: value.size.to_i,
|
329
|
-
uploaded_at: Time.now,
|
330
|
-
paths: {},
|
331
|
-
old_paths: []
|
332
|
-
}
|
333
|
-
if value.content_type.starts_with?('image/')
|
334
|
-
width, height = Console.find_dimensions(value.path)
|
335
|
-
attributes[:width] = width
|
336
|
-
attributes[:height] = height
|
337
|
-
attributes[:ratio] = (height.to_d / width.to_d).to_f
|
338
|
-
end
|
339
|
-
[value, attributes]
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
3
|
+
include(
|
4
|
+
ActiveModel::Validations,
|
5
|
+
Attachs::Attachment::Attributes,
|
6
|
+
Attachs::Attachment::Processing
|
7
|
+
)
|
343
8
|
end
|
344
9
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Attachs
|
2
|
+
class Attachment
|
3
|
+
module Attributes
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
attr_reader :record, :record_attribute, :options, :attributes, :value, :original_attributes, :source
|
7
|
+
|
8
|
+
def initialize(record, record_attribute, options={}, attributes={})
|
9
|
+
@record = record
|
10
|
+
@record_attribute = record_attribute
|
11
|
+
@options = options
|
12
|
+
@original_attributes = @attributes = normalize_attributes(attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
%i(id size filename content_type uploaded_at).each do |name|
|
16
|
+
define_method name do
|
17
|
+
attributes[name]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def basename
|
22
|
+
if filename
|
23
|
+
File.basename filename, extension
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def extension
|
28
|
+
if filename
|
29
|
+
File.extname filename
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def present?
|
34
|
+
filename.present? && content_type.present? && size.present?
|
35
|
+
end
|
36
|
+
|
37
|
+
def blank?
|
38
|
+
!present?
|
39
|
+
end
|
40
|
+
|
41
|
+
def persisted?
|
42
|
+
record.persisted? && paths.any? && uploaded_at
|
43
|
+
end
|
44
|
+
|
45
|
+
def changed?
|
46
|
+
@original_attributes != @attributes
|
47
|
+
end
|
48
|
+
|
49
|
+
def type
|
50
|
+
if content_type
|
51
|
+
if content_type.starts_with?('image/')
|
52
|
+
'image'
|
53
|
+
else
|
54
|
+
'file'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def position
|
60
|
+
if options[:multiple]
|
61
|
+
attributes[:position]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def position=(value)
|
66
|
+
if options[:multiple]
|
67
|
+
attributes[:position] = value
|
68
|
+
write_record
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def styles
|
73
|
+
case value = options[:styles]
|
74
|
+
when Proc
|
75
|
+
value.call(record) || {}
|
76
|
+
when Hash
|
77
|
+
value
|
78
|
+
else
|
79
|
+
{}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def respond_to_missing?(name, include_private=false)
|
84
|
+
attributes.has_key?(name) || super
|
85
|
+
end
|
86
|
+
|
87
|
+
def method_missing(name, *args, &block)
|
88
|
+
if attributes.has_key?(name)
|
89
|
+
attributes[name]
|
90
|
+
else
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def normalize_attributes(attributes)
|
98
|
+
attributes.reverse_merge(paths: {}, old_paths: []).deep_symbolize_keys
|
99
|
+
end
|
100
|
+
|
101
|
+
def write_record(value=nil)
|
102
|
+
unless record.destroyed?
|
103
|
+
record.send "#{record_attribute}_will_change!"
|
104
|
+
record.send :write_attribute, record_attribute, (value || raw_attributes)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def raw_attributes
|
109
|
+
if options[:multiple]
|
110
|
+
record.send(:read_attribute, record_attribute).reject{ |h| h['id'] == id }.append attributes
|
111
|
+
else
|
112
|
+
attributes
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|