paperclip 2.3.16 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- data/README.md +140 -4
- data/lib/paperclip.rb +46 -12
- data/lib/paperclip/attachment.rb +46 -5
- data/lib/paperclip/interpolations.rb +30 -1
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +2 -2
- data/lib/paperclip/missing_attachment_styles.rb +86 -0
- data/lib/paperclip/storage/filesystem.rb +3 -0
- data/lib/paperclip/storage/fog.rb +28 -5
- data/lib/paperclip/storage/s3.rb +3 -0
- data/lib/paperclip/style.rb +7 -3
- data/lib/paperclip/thumbnail.rb +15 -4
- data/lib/paperclip/version.rb +1 -1
- data/lib/tasks/paperclip.rake +16 -0
- data/test/attachment_test.rb +82 -8
- data/test/fixtures/fog.yml +8 -0
- data/test/fog_test.rb +74 -0
- data/test/helper.rb +1 -1
- data/test/integration_test.rb +32 -0
- data/test/interpolations_test.rb +32 -1
- data/test/paperclip_missing_attachment_styles_test.rb +80 -0
- data/test/paperclip_test.rb +22 -4
- data/test/storage_test.rb +17 -0
- data/test/style_test.rb +20 -0
- data/test/thumbnail_test.rb +51 -0
- data/test/upfile_test.rb +8 -0
- metadata +191 -140
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Paperclip
|
2
|
-
=========
|
1
|
+
# Paperclip [![Build Status](https://secure.travis-ci.org/thoughtbot/paperclip.png?branch=master)](http://travis-ci.org/thoughtbot/paperclip)
|
3
2
|
|
4
3
|
Paperclip is intended as an easy file attachment library for ActiveRecord. The
|
5
4
|
intent behind it was to keep setup as easy as possible and to treat files as
|
@@ -26,13 +25,21 @@ that it does, on your command line, run `which convert` (one of the ImageMagick
|
|
26
25
|
utilities). This will give you the path where that utility is installed. For
|
27
26
|
example, it might return `/usr/local/bin/convert`.
|
28
27
|
|
29
|
-
Then, in your environment config file, let Paperclip know to look there by adding that
|
28
|
+
Then, in your environment config file, let Paperclip know to look there by adding that
|
30
29
|
directory to its path.
|
31
30
|
|
32
31
|
In development mode, you might add this line to `config/environments/development.rb)`:
|
33
32
|
|
34
33
|
Paperclip.options[:command_path] = "/usr/local/bin/"
|
35
34
|
|
35
|
+
If you're on Mac OSX, you'll want to run the following with Homebrew:
|
36
|
+
|
37
|
+
brew install imagemagick
|
38
|
+
|
39
|
+
If you are dealing with pdf uploads or running the test suite, also run:
|
40
|
+
|
41
|
+
brew install gs
|
42
|
+
|
36
43
|
Installation
|
37
44
|
------------
|
38
45
|
|
@@ -99,6 +106,11 @@ In your show view:
|
|
99
106
|
<%= image_tag @user.avatar.url(:medium) %>
|
100
107
|
<%= image_tag @user.avatar.url(:thumb) %>
|
101
108
|
|
109
|
+
To detach a file, simply set the attribute to `nil`:
|
110
|
+
|
111
|
+
@user.avatar = nil
|
112
|
+
@user.save
|
113
|
+
|
102
114
|
Usage
|
103
115
|
-----
|
104
116
|
|
@@ -219,6 +231,130 @@ Paperclip has an interpolation called `:hash` for obfuscating filenames of publi
|
|
219
231
|
|
220
232
|
[https://github.com/thoughtbot/paperclip/pull/416](https://github.com/thoughtbot/paperclip/pull/416)
|
221
233
|
|
234
|
+
MD5 Checksum / Fingerprint
|
235
|
+
-------
|
236
|
+
|
237
|
+
A MD5 checksum of the original file assigned will be placed in the model if it
|
238
|
+
has an attribute named fingerprint. Following the user model migration example
|
239
|
+
above, the migration would look like the following.
|
240
|
+
|
241
|
+
class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
|
242
|
+
def self.up
|
243
|
+
add_column :users, :avatar_fingerprint, :string
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.down
|
247
|
+
remove_column :users, :avatar_fingerprint
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
Custom Attachment Processors
|
252
|
+
-------
|
253
|
+
|
254
|
+
Custom attachment processors can be implemented and their only requirement is
|
255
|
+
to inherit from `Paperclip::Processor` (see `lib/paperclip/processor.rb`).
|
256
|
+
For example, when `:styles` are specified for an image attachment, the
|
257
|
+
thumbnail processor (see `lib/paperclip/thumbnail.rb`) is loaded without having
|
258
|
+
to specify it as a `:processor` parameter to `has_attached_file`. When any
|
259
|
+
other processor is defined it must be called out in the `:processors`
|
260
|
+
parameter if it is to be applied to the attachment. The thumbnail processor
|
261
|
+
uses the imagemagick `convert` command to do the work of resizing image
|
262
|
+
thumbnails. It would be easy to create a custom processor that watermarks
|
263
|
+
an image using imagemagick's `composite` command. Following the
|
264
|
+
implementation pattern of the thumbnail processor would be a way to implement a
|
265
|
+
watermark processor. All kinds of attachment processors can be created;
|
266
|
+
a few utility examples would be compression and encryption processors.
|
267
|
+
|
268
|
+
|
269
|
+
Dynamic Configuration
|
270
|
+
---------------------
|
271
|
+
|
272
|
+
Callable objects (labdas, Procs) can be used in a number of places for dynamic
|
273
|
+
configuration throughout Paperclip. This strategy exists in a number of
|
274
|
+
components of the library but is most significant in the possibilities for
|
275
|
+
allowing custom styles and processors to be applied for specific model
|
276
|
+
instances, rather than applying defined styles and processors across all
|
277
|
+
instances.
|
278
|
+
|
279
|
+
Dynamic Styles:
|
280
|
+
|
281
|
+
Imagine a user model that had different styles based on the role of the user.
|
282
|
+
Perhaps some users are bosses (e.g. a User model instance responds to #boss?)
|
283
|
+
and merit a bigger avatar thumbnail than regular users. The configuration to
|
284
|
+
determine what style parameters are to be used based on the user role might
|
285
|
+
look as follows where a boss will receive a `300x300` thumbnail otherwise a
|
286
|
+
`100x100` thumbnail will be created.
|
287
|
+
|
288
|
+
class User < ActiveRecord::Base
|
289
|
+
has_attached_file :avatar, :styles => lambda { |attachment| { :thumb => (attachment.instance.boss? ? "300x300>" : "100x100>") }
|
290
|
+
end
|
291
|
+
|
292
|
+
Dynamic Processors:
|
293
|
+
|
294
|
+
Another contrived example is a user model that is aware of which file processors
|
295
|
+
should be applied to it (beyond the implied `thumbnail` processor invoked when
|
296
|
+
`:styles` are defined). Perhaps we have a watermark processor available and it is
|
297
|
+
only used on the avatars of certain models. The configuration for this might be
|
298
|
+
where the instance is queried for which processors should be applied to it.
|
299
|
+
Presumably some users might return `[:thumbnail, :watermark]` for its
|
300
|
+
processors, where a defined `watermark` processor is invoked after the
|
301
|
+
`thumbnail` processor already defined by Paperclip.
|
302
|
+
|
303
|
+
class User < ActiveRecord::Base
|
304
|
+
has_attached_file :avatar, :processors => lambda { |instance| instance.processors }
|
305
|
+
attr_accessor :watermark
|
306
|
+
end
|
307
|
+
|
308
|
+
Deploy
|
309
|
+
------
|
310
|
+
|
311
|
+
Paperclip is aware of new attachment styles you have added in previous deploy. The only thing you should do after each deployment is to call
|
312
|
+
`rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
|
313
|
+
by default. You can change it by:
|
314
|
+
|
315
|
+
Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachments.yml'
|
316
|
+
|
317
|
+
Here is an example for Capistrano:
|
318
|
+
|
319
|
+
namespace :deploy do
|
320
|
+
desc "build missing paperclip styles"
|
321
|
+
task :build_missing_paperclip_styles, :roles => :app do
|
322
|
+
run "cd #{release_path}; RAILS_ENV=production bundle exec rake paperclip:refresh:missing_styles"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
after("deploy:update_code", "deploy:build_missing_paperclip_styles")
|
327
|
+
|
328
|
+
Now you don't have to remember to refresh thumbnails in production everytime you add new style.
|
329
|
+
Unfortunately it does not work with dynamic styles - it just ignores them.
|
330
|
+
|
331
|
+
If you already have working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
|
332
|
+
Paperclip about existing styles. Simply create paperclip_attachments.yml file by hand. For example:
|
333
|
+
|
334
|
+
class User < ActiveRecord::Base
|
335
|
+
has_attached_file :avatar, :styles => {:thumb => 'x100', :croppable => '600x600>', :big => '1000x1000>'}
|
336
|
+
end
|
337
|
+
|
338
|
+
class Book < ActiveRecord::Base
|
339
|
+
has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
|
340
|
+
has_attached_file :sample, :styles => {:thumb => 'x100'}
|
341
|
+
end
|
342
|
+
|
343
|
+
Then in `RAILS_ROOT/public/system/paperclip_attachments.yml`:
|
344
|
+
|
345
|
+
---
|
346
|
+
:User:
|
347
|
+
:avatar:
|
348
|
+
- :thumb
|
349
|
+
- :croppable
|
350
|
+
- :big
|
351
|
+
:Book:
|
352
|
+
:cover:
|
353
|
+
- :small
|
354
|
+
- :large
|
355
|
+
:sample:
|
356
|
+
- :thumb
|
357
|
+
|
222
358
|
Testing
|
223
359
|
-------
|
224
360
|
|
@@ -233,7 +369,7 @@ If you'd like to contribute a feature or bugfix: Thanks! To make sure your
|
|
233
369
|
fix/feature has a high chance of being included, please read the following
|
234
370
|
guidelines:
|
235
371
|
|
236
|
-
1. Ask on the mailing list[http://groups.google.com/group/paperclip-plugin], or
|
372
|
+
1. Ask on the mailing list[http://groups.google.com/group/paperclip-plugin], or
|
237
373
|
post a new GitHub Issue[http://github.com/thoughtbot/paperclip/issues].
|
238
374
|
2. Make sure there are tests! We will not accept any patch that is not tested.
|
239
375
|
It's a rare time when explicit tests aren't needed. If you have questions
|
data/lib/paperclip.rb
CHANGED
@@ -39,7 +39,9 @@ require 'paperclip/style'
|
|
39
39
|
require 'paperclip/attachment'
|
40
40
|
require 'paperclip/storage'
|
41
41
|
require 'paperclip/callback_compatibility'
|
42
|
+
require 'paperclip/missing_attachment_styles'
|
42
43
|
require 'paperclip/railtie'
|
44
|
+
require 'logger'
|
43
45
|
require 'cocaine'
|
44
46
|
|
45
47
|
# The base module that gets included in ActiveRecord::Base. See the
|
@@ -91,7 +93,7 @@ module Paperclip
|
|
91
93
|
# This method can log the command being run when
|
92
94
|
# Paperclip.options[:log_command] is set to true (defaults to false). This
|
93
95
|
# will only log if logging in general is set to true as well.
|
94
|
-
def run
|
96
|
+
def run(cmd, *params)
|
95
97
|
if options[:image_magick_path]
|
96
98
|
Paperclip.log("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
|
97
99
|
end
|
@@ -99,14 +101,16 @@ module Paperclip
|
|
99
101
|
Cocaine::CommandLine.new(cmd, *params).run
|
100
102
|
end
|
101
103
|
|
102
|
-
def processor
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
def processor(name) #:nodoc:
|
105
|
+
@known_processors ||= {}
|
106
|
+
if @known_processors[name.to_s]
|
107
|
+
@known_processors[name.to_s]
|
108
|
+
else
|
109
|
+
name = name.to_s.camelize
|
110
|
+
load_processor(name) unless Paperclip.const_defined?(name)
|
111
|
+
processor = Paperclip.const_get(name)
|
112
|
+
@known_processors[name.to_s] = processor
|
108
113
|
end
|
109
|
-
processor
|
110
114
|
end
|
111
115
|
|
112
116
|
def load_processor(name)
|
@@ -115,6 +119,23 @@ module Paperclip
|
|
115
119
|
end
|
116
120
|
end
|
117
121
|
|
122
|
+
def clear_processors!
|
123
|
+
@known_processors.try(:clear)
|
124
|
+
end
|
125
|
+
|
126
|
+
# You can add your own processor via the Paperclip configuration. Normally
|
127
|
+
# Paperclip will load all processors from the
|
128
|
+
# Rails.root/lib/paperclip_processors directory, but here you can add any
|
129
|
+
# existing class using this mechanism.
|
130
|
+
#
|
131
|
+
# Paperclip.configure do |c|
|
132
|
+
# c.register_processor :watermarker, WatermarkingProcessor.new
|
133
|
+
# end
|
134
|
+
def register_processor(name, processor)
|
135
|
+
@known_processors ||= {}
|
136
|
+
@known_processors[name.to_s] = processor
|
137
|
+
end
|
138
|
+
|
118
139
|
def each_instance_with_attachment(klass, name)
|
119
140
|
class_for(klass).all.each do |instance|
|
120
141
|
yield(instance) if instance.send(:"#{name}?")
|
@@ -128,7 +149,11 @@ module Paperclip
|
|
128
149
|
end
|
129
150
|
|
130
151
|
def logger #:nodoc:
|
131
|
-
|
152
|
+
@logger ||= options[:logger] || Logger.new(STDOUT)
|
153
|
+
end
|
154
|
+
|
155
|
+
def logger=(logger)
|
156
|
+
@logger = logger
|
132
157
|
end
|
133
158
|
|
134
159
|
def logging? #:nodoc:
|
@@ -264,9 +289,11 @@ module Paperclip
|
|
264
289
|
end
|
265
290
|
|
266
291
|
attachment_definitions[name] = {:validations => []}.merge(options)
|
292
|
+
Paperclip.classes_with_attachments << self
|
267
293
|
|
268
294
|
after_save :save_attached_files
|
269
|
-
before_destroy :
|
295
|
+
before_destroy :prepare_for_destroy
|
296
|
+
after_destroy :destroy_attached_files
|
270
297
|
|
271
298
|
define_paperclip_callbacks :post_process, :"#{name}_post_process"
|
272
299
|
|
@@ -328,7 +355,7 @@ module Paperclip
|
|
328
355
|
# be run is this lambda or method returns true.
|
329
356
|
# * +unless+: Same as +if+ but validates if lambda or method returns false.
|
330
357
|
def validates_attachment_presence name, options = {}
|
331
|
-
message = options[:message] ||
|
358
|
+
message = options[:message] || :empty
|
332
359
|
validates_presence_of :"#{name}_file_name",
|
333
360
|
:message => message,
|
334
361
|
:if => options[:if],
|
@@ -402,10 +429,17 @@ module Paperclip
|
|
402
429
|
def destroy_attached_files
|
403
430
|
Paperclip.log("Deleting attachments.")
|
404
431
|
each_attachment do |name, attachment|
|
405
|
-
attachment.send(:queue_existing_for_delete)
|
406
432
|
attachment.send(:flush_deletes)
|
407
433
|
end
|
408
434
|
end
|
435
|
+
|
436
|
+
def prepare_for_destroy
|
437
|
+
Paperclip.log("Scheduling attachments for deletion.")
|
438
|
+
each_attachment do |name, attachment|
|
439
|
+
attachment.send(:queue_existing_for_delete)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
409
443
|
end
|
410
444
|
|
411
445
|
end
|
data/lib/paperclip/attachment.rb
CHANGED
@@ -14,6 +14,7 @@ module Paperclip
|
|
14
14
|
:only_process => [],
|
15
15
|
:processors => [:thumbnail],
|
16
16
|
:convert_options => {},
|
17
|
+
:source_file_options => {},
|
17
18
|
:default_url => "/:attachment/:style/missing.png",
|
18
19
|
:default_style => :original,
|
19
20
|
:storage => :filesystem,
|
@@ -26,12 +27,33 @@ module Paperclip
|
|
26
27
|
}
|
27
28
|
end
|
28
29
|
|
29
|
-
attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny, :options
|
30
|
+
attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny, :options, :source_file_options, :interpolator
|
30
31
|
attr_accessor :post_processing
|
31
32
|
|
32
33
|
# Creates an Attachment object. +name+ is the name of the attachment,
|
33
34
|
# +instance+ is the ActiveRecord object instance it's attached to, and
|
34
35
|
# +options+ is the same as the hash passed to +has_attached_file+.
|
36
|
+
#
|
37
|
+
# Options include:
|
38
|
+
#
|
39
|
+
# +url+ - a relative URL of the attachment. This is interpolated using +interpolator+
|
40
|
+
# +path+ - where on the filesystem to store the attachment. This is interpolated using +interpolator+
|
41
|
+
# +styles+ - a hash of options for processing the attachment. See +has_attached_file+ for the details
|
42
|
+
# +only_process+ - style args to be run through the post-processor. This defaults to the empty list
|
43
|
+
# +default_url+ - a URL for the missing image
|
44
|
+
# +default_style+ - the style to use when don't specify an argument to e.g. #url, #path
|
45
|
+
# +storage+ - the storage mechanism. Defaults to :filesystem
|
46
|
+
# +use_timestamp+ - whether to append an anti-caching timestamp to image URLs. Defaults to true
|
47
|
+
# +whiny+, +whiny_thumbnails+ - whether to raise when thumbnailing fails
|
48
|
+
# +use_default_time_zone+ - related to +use_timestamp+. Defaults to true
|
49
|
+
# +hash_digest+ - a string representing a class that will be used to hash URLs for obfuscation
|
50
|
+
# +hash_data+ - the relative URL for the hash data. This is interpolated using +interpolator+
|
51
|
+
# +hash_secret+ - a secret passed to the +hash_digest+
|
52
|
+
# +convert_options+ - flags passed to the +convert+ command for processing
|
53
|
+
# +source_file_options+ - flags passed to the +convert+ command that controls how the file is read
|
54
|
+
# +processors+ - classes that transform the attachment. Defaults to [:thumbnail]
|
55
|
+
# +preserve_files+ - whether to keep files on the filesystem when deleting to clearing the attachment. Defaults to false
|
56
|
+
# +interpolator+ - the object used to interpolate filenames and URLs. Defaults to Paperclip::Interpolations
|
35
57
|
def initialize name, instance, options = {}
|
36
58
|
@name = name
|
37
59
|
@instance = instance
|
@@ -55,6 +77,7 @@ module Paperclip
|
|
55
77
|
@hash_data = options[:hash_data]
|
56
78
|
@hash_secret = options[:hash_secret]
|
57
79
|
@convert_options = options[:convert_options]
|
80
|
+
@source_file_options = options[:source_file_options]
|
58
81
|
@processors = options[:processors]
|
59
82
|
@preserve_files = options[:preserve_files]
|
60
83
|
@options = options
|
@@ -63,6 +86,7 @@ module Paperclip
|
|
63
86
|
@queued_for_write = {}
|
64
87
|
@errors = {}
|
65
88
|
@dirty = false
|
89
|
+
@interpolator = (options[:interpolator] || Paperclip::Interpolations)
|
66
90
|
|
67
91
|
initialize_storage
|
68
92
|
end
|
@@ -111,7 +135,7 @@ module Paperclip
|
|
111
135
|
|
112
136
|
@dirty = true
|
113
137
|
|
114
|
-
post_process(*@only_process) if
|
138
|
+
post_process(*@only_process) if post_processing
|
115
139
|
|
116
140
|
# Reset the file size if the original file was reprocessed.
|
117
141
|
instance_write(:file_size, @queued_for_write[:original].size.to_i)
|
@@ -136,7 +160,7 @@ module Paperclip
|
|
136
160
|
# file is stored in the filesystem the path refers to the path of the file
|
137
161
|
# on disk. If the file is stored in S3, the path is the "key" part of the
|
138
162
|
# URL, and the :bucket option refers to the S3 bucket.
|
139
|
-
def path
|
163
|
+
def path(style_name = default_style)
|
140
164
|
original_filename.nil? ? nil : interpolate(@path, style_name)
|
141
165
|
end
|
142
166
|
|
@@ -341,6 +365,15 @@ module Paperclip
|
|
341
365
|
[ style_options, all_options ].compact.join(" ")
|
342
366
|
end
|
343
367
|
|
368
|
+
def extra_source_file_options_for(style) #:nodoc:
|
369
|
+
all_options = source_file_options[:all]
|
370
|
+
all_options = all_options.call(instance) if all_options.respond_to?(:call)
|
371
|
+
style_options = source_file_options[style]
|
372
|
+
style_options = style_options.call(instance) if style_options.respond_to?(:call)
|
373
|
+
|
374
|
+
[ style_options, all_options ].compact.join(" ")
|
375
|
+
end
|
376
|
+
|
344
377
|
def post_process(*style_args) #:nodoc:
|
345
378
|
return if @queued_for_write[:original].nil?
|
346
379
|
instance.run_paperclip_callbacks(:post_process) do
|
@@ -366,8 +399,8 @@ module Paperclip
|
|
366
399
|
end
|
367
400
|
end
|
368
401
|
|
369
|
-
def interpolate
|
370
|
-
|
402
|
+
def interpolate(pattern, style_name = default_style) #:nodoc:
|
403
|
+
interpolator.interpolate(pattern, self, style_name)
|
371
404
|
end
|
372
405
|
|
373
406
|
def queue_existing_for_delete #:nodoc:
|
@@ -387,5 +420,13 @@ module Paperclip
|
|
387
420
|
end
|
388
421
|
end
|
389
422
|
|
423
|
+
# called by storage after the writes are flushed and before @queued_for_writes is cleared
|
424
|
+
def after_flush_writes
|
425
|
+
@queued_for_write.each do |style, file|
|
426
|
+
file.close unless file.closed?
|
427
|
+
file.unlink if file.respond_to?(:unlink) && file.path.present? && File.exist?(file.path)
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
390
431
|
end
|
391
432
|
end
|
@@ -94,6 +94,31 @@ module Paperclip
|
|
94
94
|
File.extname(attachment.original_filename).gsub(/^\.+/, "")
|
95
95
|
end
|
96
96
|
|
97
|
+
# Returns an extension based on the content type. e.g. "jpeg" for "image/jpeg".
|
98
|
+
# Each mime type generally has multiple extensions associated with it, so
|
99
|
+
# if the extension from teh original filename is one of these extensions,
|
100
|
+
# that extension is used, otherwise, the first in the list is used.
|
101
|
+
def content_type_extension attachment, style_name
|
102
|
+
mime_type = MIME::Types[attachment.content_type]
|
103
|
+
extensions_for_mime_type = unless mime_type.empty?
|
104
|
+
mime_type.first.extensions
|
105
|
+
else
|
106
|
+
[]
|
107
|
+
end
|
108
|
+
|
109
|
+
original_extension = extension(attachment, style_name)
|
110
|
+
if extensions_for_mime_type.include? original_extension
|
111
|
+
original_extension
|
112
|
+
elsif !extensions_for_mime_type.empty?
|
113
|
+
extensions_for_mime_type.first
|
114
|
+
else
|
115
|
+
# It's possible, though unlikely, that the mime type is not in the
|
116
|
+
# database, so just use the part after the '/' in the mime type as the
|
117
|
+
# extension.
|
118
|
+
%r{/([^/]*)$}.match(attachment.content_type)[1]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
97
122
|
# Returns the id of the instance.
|
98
123
|
def id attachment, style_name
|
99
124
|
attachment.instance.id
|
@@ -118,7 +143,11 @@ module Paperclip
|
|
118
143
|
# Returns the id of the instance in a split path form. e.g. returns
|
119
144
|
# 000/001/234 for an id of 1234.
|
120
145
|
def id_partition attachment, style_name
|
121
|
-
(
|
146
|
+
if (id = attachment.instance.id).is_a?(Integer)
|
147
|
+
("%09d" % id).scan(/\d{3}/).join("/")
|
148
|
+
else
|
149
|
+
id.scan(/.{3}/).first(3).join("/")
|
150
|
+
end
|
122
151
|
end
|
123
152
|
|
124
153
|
# Returns the pluralized form of the attachment name. e.g.
|