paperclip-cloudfiles 2.3.1.1.6 → 2.3.2
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.
- 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
|
|