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 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
- include_file_globs = ["README*",
49
- "LICENSE",
50
- "Rakefile",
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
- if defined? RAILS_ROOT
40
- Dir.glob(File.join(File.expand_path(RAILS_ROOT), "lib", "paperclip_processors", "*.rb")).each do |processor|
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.1.1.6"
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 => false,
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 a string of parameters
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 = "", expected_outcodes = 0
98
- command = %Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ")
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 [expected_outcodes].flatten.include?($?.exitstatus)
103
- raise PaperclipCommandLineError, "Error while running #{cmd}"
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
- unless base.respond_to?(:define_callbacks)
115
- base.send(:include, Paperclip::CallbackCompatability)
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
- # field to pass in various convert command options. Typical options are "-strip" to
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
- define_callbacks :before_post_process, :after_post_process
226
- define_callbacks :"before_#{name}_post_process", :"after_#{name}_post_process"
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.add(:"#{name}_content_type", :inclusion, :default => options[:message], :value => value)
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
- logger.info("[paperclip] Saving attachments.")
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
- logger.info("[paperclip] Deleting attachments.")
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)
@@ -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.gsub(/[^A-Za-z\d\.\-_]+/, '_'))
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
- return if fire_events(:before)
349
- post_process_styles
350
- return if fire_events(:after)
351
- end
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
- def self.included(base)
6
- base.extend(ClassMethods)
7
- base.send(:include, InstanceMethods)
8
- end
3
+ module Rails21
4
+ def self.included(base)
5
+ base.extend(Defining)
6
+ base.send(:include, Running)
7
+ end
9
8
 
10
- module ClassMethods
11
- # The implementation of this method is taken from the Rails 1.2.6 source,
12
- # from rails/activerecord/lib/active_record/callbacks.rb, line 192.
13
- def define_callbacks(*args)
14
- args.each do |method|
15
- self.class_eval <<-"end_eval"
16
- def self.#{method}(*callbacks, &block)
17
- callbacks << block if block_given?
18
- write_inheritable_array(#{method.to_sym.inspect}, callbacks)
19
- end
20
- end_eval
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 InstanceMethods
26
- # The callbacks in < 2.1 don't worry about the extra options or the
27
- # block, so just run what we have available.
28
- def run_callbacks(meth, opts = nil, &blk)
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
@@ -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", %Q[-format "%wx%h" "#{file}"[0]])
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 RAILS_ROOT constant.
54
+ # Returns the Rails.root constant.
55
55
  def rails_root attachment, style_name
56
- RAILS_ROOT
56
+ Rails.root
57
57
  end
58
58
 
59
- # Returns the RAILS_ENV constant.
59
+ # Returns the Rails.env constant.
60
60
  def rails_env attachment, style_name
61
- RAILS_ENV
61
+ Rails.env
62
62
  end
63
63
 
64
64
  # Returns the underscored, pluralized version of the class name.
@@ -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.basename(name))
8
+ tempfile = Paperclip::Tempfile.new("stream" + File.extname(name))
9
9
  tempfile.binmode
10
10
  self.stream_to(tempfile)
11
11
  end
@@ -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