paperclip-cloudfiles 2.3.1.1.6 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -0
- data/Rakefile +9 -38
- data/lib/paperclip.rb +51 -18
- data/lib/paperclip/attachment.rb +6 -13
- data/lib/paperclip/callback_compatability.rb +50 -22
- data/lib/paperclip/geometry.rb +1 -1
- data/lib/paperclip/interpolations.rb +4 -4
- data/lib/paperclip/iostream.rb +1 -1
- data/lib/paperclip/matchers.rb +29 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +8 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +11 -1
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +9 -2
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +12 -1
- data/lib/paperclip/storage.rb +17 -17
- data/lib/paperclip/thumbnail.rb +16 -13
- data/lib/paperclip/upfile.rb +5 -1
- data/shoulda_macros/paperclip.rb +4 -2
- data/test/attachment_test.rb +11 -17
- data/test/helper.rb +61 -21
- data/test/interpolations_test.rb +4 -4
- data/test/iostream_test.rb +1 -1
- data/test/matchers/have_attached_file_matcher_test.rb +9 -6
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +14 -8
- data/test/matchers/validate_attachment_presence_matcher_test.rb +8 -5
- data/test/matchers/validate_attachment_size_matcher_test.rb +17 -17
- data/test/paperclip_test.rb +24 -25
- data/test/storage_test.rb +32 -19
- data/test/thumbnail_test.rb +6 -6
- data/test/upfile_test.rb +8 -0
- metadata +30 -19
data/README.rdoc
CHANGED
@@ -174,6 +174,11 @@ NOTE: Post processing will not even *start* if the attachment is not valid
|
|
174
174
|
according to the validations. Your callbacks and processors will *only* be
|
175
175
|
called with valid attachments.
|
176
176
|
|
177
|
+
==Testing
|
178
|
+
|
179
|
+
Paperclip provides rspec-compatible matchers for testing attachments. See the
|
180
|
+
documentation on Paperclip::Shoulda::Matchers for more information.
|
181
|
+
|
177
182
|
==Contributing
|
178
183
|
|
179
184
|
If you'd like to contribute a feature or bugfix: Thanks! To make sure your
|
data/Rakefile
CHANGED
@@ -8,6 +8,11 @@ require 'paperclip'
|
|
8
8
|
desc 'Default: run unit tests.'
|
9
9
|
task :default => [:clean, :test]
|
10
10
|
|
11
|
+
desc 'Test the paperclip plugin under all supported Rails versions.'
|
12
|
+
task :all do |t|
|
13
|
+
exec('rake RAILS_VERSION=2.1 && rake RAILS_VERSION=2.3 && rake RAILS_VERSION=3.0')
|
14
|
+
end
|
15
|
+
|
11
16
|
desc 'Test the paperclip plugin.'
|
12
17
|
Rake::TestTask.new(:test) do |t|
|
13
18
|
t.libs << 'lib' << 'profile'
|
@@ -40,49 +45,15 @@ task :clean do |t|
|
|
40
45
|
FileUtils.rm_rf "doc"
|
41
46
|
FileUtils.rm_rf "tmp"
|
42
47
|
FileUtils.rm_rf "pkg"
|
48
|
+
FileUtils.rm_rf "public"
|
43
49
|
FileUtils.rm "test/debug.log" rescue nil
|
44
50
|
FileUtils.rm "test/paperclip.db" rescue nil
|
45
51
|
Dir.glob("paperclip-*.gem").each{|f| FileUtils.rm f }
|
46
52
|
end
|
47
53
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
"init.rb",
|
52
|
-
"{generators,lib,tasks,test,shoulda_macros}/**/*"]
|
53
|
-
exclude_file_globs = ["test/s3.yml",
|
54
|
-
"test/debug.log",
|
55
|
-
"test/paperclip.db",
|
56
|
-
"test/doc",
|
57
|
-
"test/doc/*",
|
58
|
-
"test/pkg",
|
59
|
-
"test/pkg/*",
|
60
|
-
"test/tmp",
|
61
|
-
"test/tmp/*"]
|
62
|
-
spec = Gem::Specification.new do |s|
|
63
|
-
s.name = "paperclip-cloudfiles"
|
64
|
-
s.version = Paperclip::VERSION
|
65
|
-
s.authors = "Jon Yurek", "H. Wade Minter"
|
66
|
-
s.email = "jyurek@thoughtbot.com", "minter@lunenburg.org"
|
67
|
-
s.homepage = "http://github.com/minter/paperclip"
|
68
|
-
s.platform = Gem::Platform::RUBY
|
69
|
-
s.description = "A fork of the Thoughtbot Paperclip gem/plugin, adding support for Rackspace Cloud Files. This fork is maintained by H. Wade Minter <minter@lunenburg.org>"
|
70
|
-
s.summary = "File attachments as attributes for ActiveRecord with Rackspace Cloud Files support"
|
71
|
-
s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
|
72
|
-
s.require_path = "lib"
|
73
|
-
s.test_files = FileList["test/**/test_*.rb"].to_a
|
74
|
-
s.rubyforge_project = "paperclip"
|
75
|
-
s.has_rdoc = true
|
76
|
-
s.extra_rdoc_files = FileList["README*"].to_a
|
77
|
-
s.rdoc_options << '--line-numbers' << '--inline-source'
|
78
|
-
s.requirements << "ImageMagick"
|
79
|
-
s.add_development_dependency 'shoulda'
|
80
|
-
s.add_development_dependency 'jferris-mocha', '>= 0.9.5.0.1241126838'
|
81
|
-
s.add_development_dependency 'aws-s3'
|
82
|
-
s.add_development_dependency 'cloudfiles', '>= 1.4.4'
|
83
|
-
s.add_development_dependency 'sqlite3-ruby'
|
84
|
-
s.add_development_dependency 'activerecord'
|
85
|
-
s.add_development_dependency 'activesupport'
|
54
|
+
desc 'Build the gemspec.'
|
55
|
+
task :gemspec do |t|
|
56
|
+
exec 'gem build paperclip-cloudfiles.gemspec'
|
86
57
|
end
|
87
58
|
|
88
59
|
desc "Print a list of the files to be put into the gem"
|
data/lib/paperclip.rb
CHANGED
@@ -36,8 +36,9 @@ require 'paperclip/storage'
|
|
36
36
|
require 'paperclip/interpolations'
|
37
37
|
require 'paperclip/style'
|
38
38
|
require 'paperclip/attachment'
|
39
|
-
|
40
|
-
|
39
|
+
require 'paperclip/callback_compatability'
|
40
|
+
if defined?(Rails.root) && Rails.root
|
41
|
+
Dir.glob(File.join(File.expand_path(Rails.root), "lib", "paperclip_processors", "*.rb")).each do |processor|
|
41
42
|
require processor
|
42
43
|
end
|
43
44
|
end
|
@@ -46,7 +47,7 @@ end
|
|
46
47
|
# documentation for Paperclip::ClassMethods for more useful information.
|
47
48
|
module Paperclip
|
48
49
|
|
49
|
-
VERSION = "2.3.
|
50
|
+
VERSION = "2.3.2"
|
50
51
|
|
51
52
|
class << self
|
52
53
|
# Provides configurability to Paperclip. There are a number of options available, such as:
|
@@ -64,7 +65,7 @@ module Paperclip
|
|
64
65
|
:image_magick_path => nil,
|
65
66
|
:command_path => nil,
|
66
67
|
:log => true,
|
67
|
-
:log_command =>
|
68
|
+
:log_command => true,
|
68
69
|
:swallow_stderr => true
|
69
70
|
}
|
70
71
|
end
|
@@ -81,7 +82,7 @@ module Paperclip
|
|
81
82
|
Paperclip::Interpolations[key] = block
|
82
83
|
end
|
83
84
|
|
84
|
-
# The run method takes a command to execute and
|
85
|
+
# The run method takes a command to execute and an array of parameters
|
85
86
|
# that get passed to it. The command is prefixed with the :command_path
|
86
87
|
# option from Paperclip.options. If you have many commands to run and
|
87
88
|
# they are in different paths, the suggested course of action is to
|
@@ -90,29 +91,49 @@ module Paperclip
|
|
90
91
|
# If the command returns with a result code that is not one of the
|
91
92
|
# expected_outcodes, a PaperclipCommandLineError will be raised. Generally
|
92
93
|
# a code of 0 is expected, but a list of codes may be passed if necessary.
|
94
|
+
# These codes should be passed as a hash as the last argument, like so:
|
95
|
+
#
|
96
|
+
# Paperclip.run("echo", "something", :expected_outcodes => [0,1,2,3])
|
93
97
|
#
|
94
98
|
# This method can log the command being run when
|
95
99
|
# Paperclip.options[:log_command] is set to true (defaults to false). This
|
96
100
|
# will only log if logging in general is set to true as well.
|
97
|
-
def run cmd, params
|
98
|
-
|
101
|
+
def run cmd, *params
|
102
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
103
|
+
expected_outcodes = options[:expected_outcodes] || [0]
|
104
|
+
params = quote_command_options(*params).join(" ")
|
105
|
+
|
106
|
+
command = %Q[#{path_for_command(cmd)} #{params}]
|
99
107
|
command = "#{command} 2>#{bit_bucket}" if Paperclip.options[:swallow_stderr]
|
100
108
|
Paperclip.log(command) if Paperclip.options[:log_command]
|
109
|
+
|
101
110
|
output = `#{command}`
|
102
|
-
unless
|
103
|
-
raise PaperclipCommandLineError,
|
111
|
+
unless expected_outcodes.include?($?.exitstatus)
|
112
|
+
raise PaperclipCommandLineError,
|
113
|
+
"Error while running #{cmd}. Expected return code to be #{expected_outcodes.join(", ")} but was #{$?.exitstatus}",
|
114
|
+
output
|
104
115
|
end
|
105
116
|
output
|
106
117
|
end
|
107
118
|
|
119
|
+
def quote_command_options(*options)
|
120
|
+
options.map do |option|
|
121
|
+
option.split("'").map{|m| "'#{m}'" }.join("\\'")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
108
125
|
def bit_bucket #:nodoc:
|
109
126
|
File.exists?("/dev/null") ? "/dev/null" : "NUL"
|
110
127
|
end
|
111
128
|
|
112
129
|
def included base #:nodoc:
|
113
130
|
base.extend ClassMethods
|
114
|
-
|
115
|
-
base.send
|
131
|
+
if base.respond_to?("set_callback")
|
132
|
+
base.send :include, Paperclip::CallbackCompatability::Rails3
|
133
|
+
elsif !base.respond_to?("define_callbacks")
|
134
|
+
base.send :include, Paperclip::CallbackCompatability::Rails20
|
135
|
+
else
|
136
|
+
base.send :include, Paperclip::CallbackCompatability::Rails21
|
116
137
|
end
|
117
138
|
end
|
118
139
|
|
@@ -144,6 +165,11 @@ module Paperclip
|
|
144
165
|
end
|
145
166
|
|
146
167
|
class PaperclipCommandLineError < StandardError #:nodoc:
|
168
|
+
attr_accessor :output
|
169
|
+
def initialize(msg = nil, output = nil)
|
170
|
+
super(msg)
|
171
|
+
@output = output
|
172
|
+
end
|
147
173
|
end
|
148
174
|
|
149
175
|
class NotIdentifiedByImageMagickError < PaperclipError #:nodoc:
|
@@ -192,7 +218,7 @@ module Paperclip
|
|
192
218
|
# Defaults to true. This option used to be called :whiny_thumbanils, but this is
|
193
219
|
# deprecated.
|
194
220
|
# * +convert_options+: When creating thumbnails, use this free-form options
|
195
|
-
#
|
221
|
+
# array to pass in various convert command options. Typical options are "-strip" to
|
196
222
|
# remove all Exif data from the image (save space for thumbnails and avatars) or
|
197
223
|
# "-depth 8" to specify the bit depth of the resulting conversion. See ImageMagick
|
198
224
|
# convert documentation for more options: (http://www.imagemagick.org/script/convert.php)
|
@@ -209,6 +235,9 @@ module Paperclip
|
|
209
235
|
# NOTE: While not deprecated yet, it is not recommended to specify options this way.
|
210
236
|
# It is recommended that :convert_options option be included in the hash passed to each
|
211
237
|
# :styles for compatability with future versions.
|
238
|
+
# NOTE: Strings supplied to :convert_options are split on space in order to undergo
|
239
|
+
# shell quoting for safety. If your options require a space, please pre-split them
|
240
|
+
# and pass an array to :convert_options instead.
|
212
241
|
# * +storage+: Chooses the storage backend where the files will be stored. The current
|
213
242
|
# choices are :filesystem and :s3. The default is :filesystem. Make sure you read the
|
214
243
|
# documentation for Paperclip::Storage::Filesystem and Paperclip::Storage::S3
|
@@ -222,9 +251,8 @@ module Paperclip
|
|
222
251
|
after_save :save_attached_files
|
223
252
|
before_destroy :destroy_attached_files
|
224
253
|
|
225
|
-
|
226
|
-
|
227
|
-
|
254
|
+
define_paperclip_callbacks :post_process, :"#{name}_post_process"
|
255
|
+
|
228
256
|
define_method name do |*args|
|
229
257
|
a = attachment_for(name)
|
230
258
|
(args.length > 0) ? a.to_s(args.first) : a
|
@@ -308,7 +336,12 @@ module Paperclip
|
|
308
336
|
types = [options.delete(:content_type)].flatten
|
309
337
|
validates_each(:"#{name}_content_type", options) do |record, attr, value|
|
310
338
|
unless types.any?{|t| t === value }
|
311
|
-
record.errors.
|
339
|
+
if record.errors.method(:add).arity == -2
|
340
|
+
message = options[:message] || "is not one of #{types.join(", ")}"
|
341
|
+
record.errors.add(:"#{name}_content_type", message)
|
342
|
+
else
|
343
|
+
record.errors.add(:"#{name}_content_type", :inclusion, :default => options[:message], :value => value)
|
344
|
+
end
|
312
345
|
end
|
313
346
|
end
|
314
347
|
end
|
@@ -333,14 +366,14 @@ module Paperclip
|
|
333
366
|
end
|
334
367
|
|
335
368
|
def save_attached_files
|
336
|
-
|
369
|
+
Paperclip.log("Saving attachments.")
|
337
370
|
each_attachment do |name, attachment|
|
338
371
|
attachment.send(:save)
|
339
372
|
end
|
340
373
|
end
|
341
374
|
|
342
375
|
def destroy_attached_files
|
343
|
-
|
376
|
+
Paperclip.log("Deleting attachments.")
|
344
377
|
each_attachment do |name, attachment|
|
345
378
|
attachment.send(:queue_existing_for_delete)
|
346
379
|
attachment.send(:flush_deletes)
|
data/lib/paperclip/attachment.rb
CHANGED
@@ -92,7 +92,7 @@ module Paperclip
|
|
92
92
|
return nil if uploaded_file.nil?
|
93
93
|
|
94
94
|
@queued_for_write[:original] = uploaded_file.to_tempfile
|
95
|
-
instance_write(:file_name, uploaded_file.original_filename.strip
|
95
|
+
instance_write(:file_name, uploaded_file.original_filename.strip)
|
96
96
|
instance_write(:content_type, uploaded_file.content_type.to_s.strip)
|
97
97
|
instance_write(:file_size, uploaded_file.size.to_i)
|
98
98
|
instance_write(:updated_at, Time.now)
|
@@ -345,18 +345,11 @@ module Paperclip
|
|
345
345
|
|
346
346
|
def post_process #:nodoc:
|
347
347
|
return if @queued_for_write[:original].nil?
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
def fire_events(which) #:nodoc:
|
354
|
-
return true if callback(:"#{which}_post_process") == false
|
355
|
-
return true if callback(:"#{which}_#{name}_post_process") == false
|
356
|
-
end
|
357
|
-
|
358
|
-
def callback which #:nodoc:
|
359
|
-
instance.run_callbacks(which, @queued_for_write){|result, obj| result == false }
|
348
|
+
instance.run_paperclip_callbacks(:post_process) do
|
349
|
+
instance.run_paperclip_callbacks(:"#{name}_post_process") do
|
350
|
+
post_process_styles
|
351
|
+
end
|
352
|
+
end
|
360
353
|
end
|
361
354
|
|
362
355
|
def post_process_styles #:nodoc:
|
@@ -1,33 +1,61 @@
|
|
1
1
|
module Paperclip
|
2
|
-
# This module is intended as a compatability shim for the differences in
|
3
|
-
# callbacks between Rails 2.0 and Rails 2.1.
|
4
2
|
module CallbackCompatability
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Rails21
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(Defining)
|
6
|
+
base.send(:include, Running)
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
9
|
+
module Defining
|
10
|
+
def define_paperclip_callbacks(*args)
|
11
|
+
args.each do |callback|
|
12
|
+
define_callbacks("before_#{callback}")
|
13
|
+
define_callbacks("after_#{callback}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Running
|
19
|
+
def run_paperclip_callbacks(callback, opts = nil, &blk)
|
20
|
+
# The overall structure of this isn't ideal since after callbacks run even if
|
21
|
+
# befores return false. But this is how rails 3's callbacks work, unfortunately.
|
22
|
+
if run_callbacks(:"before_#{callback}"){ |result, object| result == false } != false
|
23
|
+
blk.call
|
24
|
+
end
|
25
|
+
run_callbacks(:"after_#{callback}"){ |result, object| result == false }
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
25
|
-
module
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
callback(meth)
|
30
|
+
module Rails3
|
31
|
+
def self.included(base)
|
32
|
+
base.extend(Defining)
|
33
|
+
base.send(:include, Running)
|
30
34
|
end
|
35
|
+
|
36
|
+
module Defining
|
37
|
+
def define_paperclip_callbacks(*callbacks)
|
38
|
+
define_callbacks *[callbacks, {:terminator => "result == false"}].flatten
|
39
|
+
callbacks.each do |callback|
|
40
|
+
eval <<-end_callbacks
|
41
|
+
def before_#{callback}(*args, &blk)
|
42
|
+
set_callback(:#{callback}, :before, *args, &blk)
|
43
|
+
end
|
44
|
+
def after_#{callback}(*args, &blk)
|
45
|
+
set_callback(:#{callback}, :after, *args, &blk)
|
46
|
+
end
|
47
|
+
end_callbacks
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module Running
|
53
|
+
def run_paperclip_callbacks(callback, opts = nil, &block)
|
54
|
+
run_callbacks(callback, opts, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
31
58
|
end
|
59
|
+
|
32
60
|
end
|
33
61
|
end
|
data/lib/paperclip/geometry.rb
CHANGED
@@ -16,7 +16,7 @@ module Paperclip
|
|
16
16
|
def self.from_file file
|
17
17
|
file = file.path if file.respond_to? "path"
|
18
18
|
geometry = begin
|
19
|
-
Paperclip.run("identify",
|
19
|
+
Paperclip.run("identify", "-format", "%wx%h", "#{file}[0]")
|
20
20
|
rescue PaperclipCommandLineError
|
21
21
|
""
|
22
22
|
end
|
@@ -51,14 +51,14 @@ module Paperclip
|
|
51
51
|
attachment.instance_read(:updated_at).to_s
|
52
52
|
end
|
53
53
|
|
54
|
-
# Returns the
|
54
|
+
# Returns the Rails.root constant.
|
55
55
|
def rails_root attachment, style_name
|
56
|
-
|
56
|
+
Rails.root
|
57
57
|
end
|
58
58
|
|
59
|
-
# Returns the
|
59
|
+
# Returns the Rails.env constant.
|
60
60
|
def rails_env attachment, style_name
|
61
|
-
|
61
|
+
Rails.env
|
62
62
|
end
|
63
63
|
|
64
64
|
# Returns the underscored, pluralized version of the class name.
|
data/lib/paperclip/iostream.rb
CHANGED
@@ -5,7 +5,7 @@ module IOStream
|
|
5
5
|
# Returns a Tempfile containing the contents of the readable object.
|
6
6
|
def to_tempfile
|
7
7
|
name = respond_to?(:original_filename) ? original_filename : (respond_to?(:path) ? path : "stream")
|
8
|
-
tempfile = Paperclip::Tempfile.new(File.
|
8
|
+
tempfile = Paperclip::Tempfile.new("stream" + File.extname(name))
|
9
9
|
tempfile.binmode
|
10
10
|
self.stream_to(tempfile)
|
11
11
|
end
|
data/lib/paperclip/matchers.rb
CHANGED
@@ -2,3 +2,32 @@ require 'paperclip/matchers/have_attached_file_matcher'
|
|
2
2
|
require 'paperclip/matchers/validate_attachment_presence_matcher'
|
3
3
|
require 'paperclip/matchers/validate_attachment_content_type_matcher'
|
4
4
|
require 'paperclip/matchers/validate_attachment_size_matcher'
|
5
|
+
|
6
|
+
module Paperclip
|
7
|
+
module Shoulda
|
8
|
+
# Provides rspec-compatible matchers for testing Paperclip attachments.
|
9
|
+
#
|
10
|
+
# In spec_helper.rb, you'll need to require the matchers:
|
11
|
+
#
|
12
|
+
# require "paperclip/matchers"
|
13
|
+
#
|
14
|
+
# And include the module:
|
15
|
+
#
|
16
|
+
# Spec::Runner.configure do |config|
|
17
|
+
# config.include Paperclip::Shoulda::Matchers
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
# describe User do
|
22
|
+
# it { should have_attached_file(:avatar) }
|
23
|
+
# it { should validate_attachment_presence(:avatar) }
|
24
|
+
# it { should validate_attachment_content_type(:avatar).
|
25
|
+
# allowing('image/png', 'image/gif').
|
26
|
+
# rejecting('text/plain', 'text/xml') }
|
27
|
+
# it { should validate_attachment_size(:avatar).
|
28
|
+
# less_than(2.megabytes) }
|
29
|
+
# end
|
30
|
+
module Matchers
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module Paperclip
|
2
2
|
module Shoulda
|
3
3
|
module Matchers
|
4
|
+
# Ensures that the given instance or class has an attachment with the
|
5
|
+
# given name.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# describe User do
|
9
|
+
# it { should have_attached_file(:avatar) }
|
10
|
+
# end
|
4
11
|
def have_attached_file name
|
5
12
|
HaveAttachedFileMatcher.new(name)
|
6
13
|
end
|
@@ -12,6 +19,7 @@ module Paperclip
|
|
12
19
|
|
13
20
|
def matches? subject
|
14
21
|
@subject = subject
|
22
|
+
@subject = @subject.class unless Class === @subject
|
15
23
|
responds? && has_column? && included?
|
16
24
|
end
|
17
25
|
|