paperclip 2.8.0 → 3.0.2
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/.gitignore +1 -0
- data/.travis.yml +9 -7
- data/Appraisals +6 -12
- data/Gemfile +2 -0
- data/NEWS +24 -0
- data/README.md +53 -21
- data/Rakefile +7 -2
- data/UPGRADING +14 -0
- data/features/basic_integration.feature +8 -8
- data/features/rake_tasks.feature +1 -1
- data/features/step_definitions/attachment_steps.rb +11 -2
- data/features/step_definitions/rails_steps.rb +17 -79
- data/features/support/env.rb +3 -0
- data/features/support/file_helpers.rb +24 -0
- data/features/support/rails.rb +3 -3
- data/gemfiles/{rails3_1.gemfile → 3.0.gemfile} +3 -1
- data/gemfiles/{rails2.gemfile → 3.1.gemfile} +3 -1
- data/gemfiles/{rails3.gemfile → 3.2.gemfile} +3 -1
- data/images.rake +21 -0
- data/lib/generators/paperclip/paperclip_generator.rb +1 -2
- data/lib/paperclip.rb +48 -319
- data/lib/paperclip/attachment.rb +33 -81
- data/lib/paperclip/attachment_options.rb +0 -1
- data/lib/paperclip/callbacks.rb +30 -0
- data/lib/paperclip/errors.rb +27 -0
- data/lib/paperclip/geometry.rb +6 -4
- data/lib/paperclip/glue.rb +15 -0
- data/lib/paperclip/helpers.rb +71 -0
- data/lib/paperclip/instance_methods.rb +35 -0
- data/lib/paperclip/interpolations.rb +2 -2
- data/lib/paperclip/io_adapters/attachment_adapter.rb +62 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +81 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +12 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +34 -0
- data/lib/paperclip/io_adapters/registry.rb +32 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +64 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +63 -0
- data/lib/paperclip/locales/en.yml +17 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +1 -1
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -2
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +7 -7
- data/lib/paperclip/processor.rb +32 -17
- data/lib/paperclip/railtie.rb +10 -15
- data/lib/paperclip/storage/filesystem.rb +5 -14
- data/lib/paperclip/storage/fog.rb +2 -21
- data/lib/paperclip/storage/s3.rb +12 -29
- data/lib/paperclip/tempfile.rb +41 -0
- data/lib/paperclip/thumbnail.rb +2 -3
- data/lib/paperclip/validators.rb +45 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +47 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +26 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +102 -0
- data/lib/paperclip/version.rb +1 -1
- data/lib/tasks/paperclip.rake +3 -11
- data/paperclip.gemspec +15 -5
- data/test/adapter_registry_test.rb +32 -0
- data/test/attachment_adapter_test.rb +48 -0
- data/test/attachment_options_test.rb +0 -13
- data/test/attachment_test.rb +27 -55
- data/test/file_adapter_test.rb +43 -0
- data/test/generator_test.rb +78 -0
- data/test/geometry_test.rb +5 -5
- data/test/helper.rb +9 -11
- data/test/identity_adapter_test.rb +8 -0
- data/test/integration_test.rb +39 -94
- data/test/interpolations_test.rb +8 -1
- data/test/matchers/validate_attachment_size_matcher_test.rb +16 -2
- data/test/nil_adapter_test.rb +25 -0
- data/test/paperclip_test.rb +30 -189
- data/test/storage/filesystem_test.rb +0 -14
- data/test/storage/fog_test.rb +0 -14
- data/test/storage/s3_live_test.rb +22 -9
- data/test/storage/s3_test.rb +70 -34
- data/test/stringio_adapter_test.rb +42 -0
- data/test/style_test.rb +10 -16
- data/test/thumbnail_test.rb +16 -10
- data/test/uploaded_file_adapter_test.rb +98 -0
- data/test/validators/attachment_content_type_validator_test.rb +140 -0
- data/test/validators/attachment_presence_validator_test.rb +85 -0
- data/test/validators/attachment_size_validator_test.rb +207 -0
- data/test/validators_test.rb +25 -0
- metadata +152 -30
- data/gemfiles/rails3_2.gemfile +0 -9
- data/generators/paperclip/USAGE +0 -5
- data/generators/paperclip/paperclip_generator.rb +0 -27
- data/generators/paperclip/templates/paperclip_migration.rb.erb +0 -19
- data/init.rb +0 -4
- data/lib/paperclip/callback_compatibility.rb +0 -61
- data/lib/paperclip/iostream.rb +0 -45
- data/lib/paperclip/upfile.rb +0 -64
- data/rails/init.rb +0 -2
- data/test/iostream_test.rb +0 -71
- data/test/upfile_test.rb +0 -53
@@ -0,0 +1,81 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class FileAdapter
|
3
|
+
def initialize(target)
|
4
|
+
@target = target
|
5
|
+
@tempfile = copy_to_tempfile(@target)
|
6
|
+
end
|
7
|
+
|
8
|
+
def original_filename
|
9
|
+
if @target.respond_to?(:original_filename)
|
10
|
+
@target.original_filename
|
11
|
+
else
|
12
|
+
File.basename(@target.path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def content_type
|
17
|
+
types = MIME::Types.type_for(original_filename)
|
18
|
+
if types.length == 0
|
19
|
+
type_from_file_command
|
20
|
+
elsif types.length == 1
|
21
|
+
types.first.content_type
|
22
|
+
else
|
23
|
+
best_content_type_option(types)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def fingerprint
|
28
|
+
@fingerprint ||= Digest::MD5.file(path).to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def size
|
32
|
+
File.size(@tempfile)
|
33
|
+
end
|
34
|
+
|
35
|
+
def nil?
|
36
|
+
@target.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def read(length = nil, buffer = nil)
|
40
|
+
@tempfile.read(length, buffer)
|
41
|
+
end
|
42
|
+
|
43
|
+
# We don't use this directly, but aws/sdk does.
|
44
|
+
def rewind
|
45
|
+
@tempfile.rewind
|
46
|
+
end
|
47
|
+
|
48
|
+
def eof?
|
49
|
+
@tempfile.eof?
|
50
|
+
end
|
51
|
+
|
52
|
+
def path
|
53
|
+
@tempfile.path
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def copy_to_tempfile(src)
|
59
|
+
dest = Tempfile.new(original_filename)
|
60
|
+
dest.binmode
|
61
|
+
FileUtils.cp(src.path, dest.path)
|
62
|
+
dest
|
63
|
+
end
|
64
|
+
|
65
|
+
def best_content_type_option(types)
|
66
|
+
types.reject {|type| type.content_type.match(/\/x-/) }.first
|
67
|
+
end
|
68
|
+
|
69
|
+
def type_from_file_command
|
70
|
+
# On BSDs, `file` doesn't give a result code of 1 if the file doesn't exist.
|
71
|
+
type = (self.original_filename.match(/\.(\w+)$/)[1] rescue "octet-stream").downcase
|
72
|
+
mime_type = (Paperclip.run("file", "-b --mime :file", :file => self.path).split(/[:;]\s+/)[0] rescue "application/x-#{type}")
|
73
|
+
mime_type = "application/x-#{type}" if mime_type.match(/\(.*?\)/)
|
74
|
+
mime_type
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Paperclip.io_adapters.register Paperclip::FileAdapter do |target|
|
80
|
+
File === target || Tempfile === target
|
81
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class NilAdapter
|
3
|
+
def initialize(target)
|
4
|
+
end
|
5
|
+
|
6
|
+
def original_filename
|
7
|
+
""
|
8
|
+
end
|
9
|
+
|
10
|
+
def content_type
|
11
|
+
""
|
12
|
+
end
|
13
|
+
|
14
|
+
def size
|
15
|
+
0
|
16
|
+
end
|
17
|
+
|
18
|
+
def nil?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def read(*args)
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def eof?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Paperclip.io_adapters.register Paperclip::NilAdapter do |target|
|
33
|
+
target.nil?
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class AdapterRegistry
|
3
|
+
class NoHandlerError < Paperclip::Error; end
|
4
|
+
|
5
|
+
attr_reader :registered_handlers
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@registered_handlers = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(handler_class, &block)
|
12
|
+
@registered_handlers << [block, handler_class]
|
13
|
+
end
|
14
|
+
|
15
|
+
def handler_for(target)
|
16
|
+
@registered_handlers.each do |tester, handler|
|
17
|
+
return handler if tester.call(target)
|
18
|
+
end
|
19
|
+
raise NoHandlerError.new("No handler found for #{target.inspect}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def registered?(target)
|
23
|
+
@registered_handlers.any? do |tester, handler|
|
24
|
+
handler === target
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def for(target)
|
29
|
+
handler_for(target).new(target)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class StringioAdapter
|
3
|
+
def initialize(target)
|
4
|
+
@target = target
|
5
|
+
@tempfile = copy_to_tempfile(@target)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_writer :original_filename, :content_type
|
9
|
+
|
10
|
+
def original_filename
|
11
|
+
@original_filename ||= @target.original_filename if @target.respond_to?(:original_filename)
|
12
|
+
@original_filename ||= "stringio.txt"
|
13
|
+
@original_filename.strip
|
14
|
+
end
|
15
|
+
|
16
|
+
def content_type
|
17
|
+
@content_type ||= @target.content_type if @target.respond_to?(:content_type)
|
18
|
+
@content_type ||= "text/plain"
|
19
|
+
@content_type.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def size
|
23
|
+
@target.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def fingerprint
|
27
|
+
Digest::MD5.hexdigest(read)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read(length = nil, buffer = nil)
|
31
|
+
@tempfile.read(length, buffer)
|
32
|
+
end
|
33
|
+
|
34
|
+
# We don't use this directly, but aws/sdk does.
|
35
|
+
def rewind
|
36
|
+
@tempfile.rewind
|
37
|
+
end
|
38
|
+
|
39
|
+
def eof?
|
40
|
+
@tempfile.eof?
|
41
|
+
end
|
42
|
+
|
43
|
+
def path
|
44
|
+
@tempfile.path
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def copy_to_tempfile(src)
|
50
|
+
dest = Tempfile.new(original_filename)
|
51
|
+
dest.binmode
|
52
|
+
while data = src.read(16*1024)
|
53
|
+
dest.write(data)
|
54
|
+
end
|
55
|
+
dest.rewind
|
56
|
+
dest
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
Paperclip.io_adapters.register Paperclip::StringioAdapter do |target|
|
63
|
+
StringIO === target
|
64
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class UploadedFileAdapter
|
3
|
+
def initialize(target)
|
4
|
+
@target = target
|
5
|
+
|
6
|
+
if @target.respond_to?(:tempfile)
|
7
|
+
@tempfile = copy_to_tempfile(@target.tempfile)
|
8
|
+
else
|
9
|
+
@tempfile = copy_to_tempfile(@target)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def original_filename
|
14
|
+
@target.original_filename
|
15
|
+
end
|
16
|
+
|
17
|
+
def content_type
|
18
|
+
@target.content_type
|
19
|
+
end
|
20
|
+
|
21
|
+
def fingerprint
|
22
|
+
@fingerprint ||= Digest::MD5.file(path).to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def size
|
26
|
+
File.size(path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def nil?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def read(length = nil, buffer = nil)
|
34
|
+
@tempfile.read(length, buffer)
|
35
|
+
end
|
36
|
+
|
37
|
+
# We don't use this directly, but aws/sdk does.
|
38
|
+
def rewind
|
39
|
+
@tempfile.rewind
|
40
|
+
end
|
41
|
+
|
42
|
+
def eof?
|
43
|
+
@tempfile.eof?
|
44
|
+
end
|
45
|
+
|
46
|
+
def path
|
47
|
+
@tempfile.path
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def copy_to_tempfile(src)
|
53
|
+
dest = Tempfile.new(original_filename)
|
54
|
+
dest.binmode
|
55
|
+
FileUtils.cp(src.path, dest.path)
|
56
|
+
dest
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Paperclip.io_adapters.register Paperclip::UploadedFileAdapter do |target|
|
62
|
+
target.class.name.include?("UploadedFile")
|
63
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Paperclip
|
2
|
+
module Logger
|
3
|
+
# Log a paperclip-specific line. This will log to STDOUT
|
4
|
+
# by default. Set Paperclip.options[:log] to false to turn off.
|
5
|
+
def log message
|
6
|
+
logger.info("[paperclip] #{message}") if logging?
|
7
|
+
end
|
8
|
+
|
9
|
+
def logger #:nodoc:
|
10
|
+
@logger ||= options[:logger] || ::Logger.new(STDOUT)
|
11
|
+
end
|
12
|
+
|
13
|
+
def logger=(logger)
|
14
|
+
@logger = logger
|
15
|
+
end
|
16
|
+
|
17
|
+
def logging? #:nodoc:
|
18
|
+
options[:log]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -39,14 +39,14 @@ module Paperclip
|
|
39
39
|
def error_when_not_valid?
|
40
40
|
@subject.send(@attachment_name).assign(nil)
|
41
41
|
@subject.valid?
|
42
|
-
|
42
|
+
@subject.errors[:"#{@attachment_name}"].present?
|
43
43
|
end
|
44
44
|
|
45
45
|
def no_error_when_valid?
|
46
46
|
@file = StringIO.new(".")
|
47
47
|
@subject.send(@attachment_name).assign(@file)
|
48
48
|
@subject.valid?
|
49
|
-
@subject.errors[:"#{@attachment_name}
|
49
|
+
@subject.errors[:"#{@attachment_name}"].blank?
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -18,7 +18,6 @@ module Paperclip
|
|
18
18
|
class ValidateAttachmentSizeMatcher
|
19
19
|
def initialize attachment_name
|
20
20
|
@attachment_name = attachment_name
|
21
|
-
@low, @high = 0, (1.0/0)
|
22
21
|
end
|
23
22
|
|
24
23
|
def less_than size
|
@@ -67,27 +66,28 @@ module Paperclip
|
|
67
66
|
override_method(file, :size){ new_size }
|
68
67
|
override_method(file, :to_tempfile){ file }
|
69
68
|
|
69
|
+
@subject.send(@attachment_name).post_processing = false
|
70
70
|
@subject.send(@attachment_name).assign(file)
|
71
71
|
@subject.valid?
|
72
72
|
@subject.errors[:"#{@attachment_name}_file_size"].blank?
|
73
|
+
ensure
|
74
|
+
@subject.send(@attachment_name).post_processing = true
|
73
75
|
end
|
74
76
|
|
75
77
|
def lower_than_low?
|
76
|
-
|
78
|
+
@low.nil? || !passes_validation_with_size(@low - 1)
|
77
79
|
end
|
78
80
|
|
79
81
|
def higher_than_low?
|
80
|
-
passes_validation_with_size(@low + 1)
|
82
|
+
@low.nil? || passes_validation_with_size(@low + 1)
|
81
83
|
end
|
82
84
|
|
83
85
|
def lower_than_high?
|
84
|
-
|
85
|
-
passes_validation_with_size(@high - 1)
|
86
|
+
@high.nil? || @high == Float::INFINITY || passes_validation_with_size(@high - 1)
|
86
87
|
end
|
87
88
|
|
88
89
|
def higher_than_high?
|
89
|
-
|
90
|
-
not passes_validation_with_size(@high + 1)
|
90
|
+
@high.nil? || @high == Float::INFINITY || !passes_validation_with_size(@high + 1)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
data/lib/paperclip/processor.rb
CHANGED
@@ -34,25 +34,40 @@ module Paperclip
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
prefix, suffix = basename, ''
|
51
|
-
end
|
37
|
+
module ProcessorHelpers
|
38
|
+
def processor(name) #:nodoc:
|
39
|
+
@known_processors ||= {}
|
40
|
+
if @known_processors[name.to_s]
|
41
|
+
@known_processors[name.to_s]
|
42
|
+
else
|
43
|
+
name = name.to_s.camelize
|
44
|
+
load_processor(name) unless Paperclip.const_defined?(name)
|
45
|
+
processor = Paperclip.const_get(name)
|
46
|
+
@known_processors[name.to_s] = processor
|
47
|
+
end
|
48
|
+
end
|
52
49
|
|
53
|
-
|
54
|
-
|
50
|
+
def load_processor(name)
|
51
|
+
if defined?(Rails.root) && Rails.root
|
52
|
+
require File.expand_path(Rails.root.join("lib", "paperclip_processors", "#{name.underscore}.rb"))
|
55
53
|
end
|
56
54
|
end
|
55
|
+
|
56
|
+
def clear_processors!
|
57
|
+
@known_processors.try(:clear)
|
58
|
+
end
|
59
|
+
|
60
|
+
# You can add your own processor via the Paperclip configuration. Normally
|
61
|
+
# Paperclip will load all processors from the
|
62
|
+
# Rails.root/lib/paperclip_processors directory, but here you can add any
|
63
|
+
# existing class using this mechanism.
|
64
|
+
#
|
65
|
+
# Paperclip.configure do |c|
|
66
|
+
# c.register_processor :watermarker, WatermarkingProcessor.new
|
67
|
+
# end
|
68
|
+
def register_processor(name, processor)
|
69
|
+
@known_processors ||= {}
|
70
|
+
@known_processors[name.to_s] = processor
|
71
|
+
end
|
57
72
|
end
|
58
73
|
end
|