paperclip 2.3.1.1 → 2.3.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.

Files changed (44) hide show
  1. data/README.rdoc +6 -1
  2. data/Rakefile +11 -38
  3. data/generators/paperclip/USAGE +2 -2
  4. data/generators/paperclip/paperclip_generator.rb +8 -8
  5. data/lib/generators/paperclip/USAGE +8 -0
  6. data/lib/generators/paperclip/paperclip_generator.rb +31 -0
  7. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  8. data/lib/paperclip.rb +113 -69
  9. data/lib/paperclip/attachment.rb +58 -146
  10. data/lib/paperclip/callback_compatability.rb +50 -22
  11. data/lib/paperclip/geometry.rb +7 -7
  12. data/lib/paperclip/interpolations.rb +21 -21
  13. data/lib/paperclip/iostream.rb +3 -2
  14. data/lib/paperclip/matchers.rb +29 -0
  15. data/lib/paperclip/matchers/have_attached_file_matcher.rb +8 -0
  16. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +13 -5
  17. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +13 -7
  18. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +16 -4
  19. data/lib/paperclip/processor.rb +2 -2
  20. data/lib/paperclip/railtie.rb +22 -0
  21. data/lib/paperclip/storage.rb +29 -25
  22. data/lib/paperclip/style.rb +90 -0
  23. data/lib/paperclip/thumbnail.rb +20 -15
  24. data/lib/paperclip/upfile.rb +5 -2
  25. data/lib/paperclip/version.rb +3 -0
  26. data/{tasks/paperclip_tasks.rake → lib/tasks/paperclip.rake} +0 -0
  27. data/rails/init.rb +2 -0
  28. data/shoulda_macros/paperclip.rb +5 -3
  29. data/test/attachment_test.rb +52 -74
  30. data/test/geometry_test.rb +1 -1
  31. data/test/helper.rb +62 -22
  32. data/test/integration_test.rb +8 -8
  33. data/test/interpolations_test.rb +4 -4
  34. data/test/iostream_test.rb +9 -2
  35. data/test/matchers/have_attached_file_matcher_test.rb +9 -6
  36. data/test/matchers/validate_attachment_content_type_matcher_test.rb +15 -8
  37. data/test/matchers/validate_attachment_presence_matcher_test.rb +11 -6
  38. data/test/matchers/validate_attachment_size_matcher_test.rb +18 -17
  39. data/test/paperclip_test.rb +58 -68
  40. data/test/storage_test.rb +53 -13
  41. data/test/style_test.rb +141 -0
  42. data/test/thumbnail_test.rb +17 -17
  43. data/test/upfile_test.rb +8 -0
  44. metadata +69 -42
@@ -138,7 +138,7 @@ For example, assuming we had this definition:
138
138
  has_attached_file :scan, :styles => { :text => { :quality => :better } },
139
139
  :processors => [:rotator, :ocr]
140
140
 
141
- then both the :rotator processor and the :ocr processor would receive the
141
+ then both the :rotator processor and the :ocr processor would receive the
142
142
  options "{ :quality => :better }". This parameter may not mean anything to one
143
143
  or more or the processors, and they are expected to ignore it.
144
144
 
@@ -162,6 +162,11 @@ NOTE: Post processing will not even *start* if the attachment is not valid
162
162
  according to the validations. Your callbacks and processors will *only* be
163
163
  called with valid attachments.
164
164
 
165
+ ==Testing
166
+
167
+ Paperclip provides rspec-compatible matchers for testing attachments. See the
168
+ documentation on Paperclip::Shoulda::Matchers for more information.
169
+
165
170
  ==Contributing
166
171
 
167
172
  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,47 +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"
64
- s.version = Paperclip::VERSION
65
- s.author = "Jon Yurek"
66
- s.email = "jyurek@thoughtbot.com"
67
- s.homepage = "http://www.thoughtbot.com/projects/paperclip"
68
- s.platform = Gem::Platform::RUBY
69
- s.summary = "File attachments as attributes for ActiveRecord"
70
- s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
71
- s.require_path = "lib"
72
- s.test_files = FileList["test/**/test_*.rb"].to_a
73
- s.rubyforge_project = "paperclip"
74
- s.has_rdoc = true
75
- s.extra_rdoc_files = FileList["README*"].to_a
76
- s.rdoc_options << '--line-numbers' << '--inline-source'
77
- s.requirements << "ImageMagick"
78
- s.add_development_dependency 'thoughtbot-shoulda'
79
- s.add_development_dependency 'jferris-mocha', '= 0.9.5.0.1241126838'
80
- s.add_development_dependency 'aws-s3'
81
- s.add_development_dependency 'sqlite3-ruby'
82
- s.add_development_dependency 'activerecord'
83
- s.add_development_dependency 'activesupport'
54
+ desc 'Build the gemspec.'
55
+ task :gemspec do |t|
56
+ exec 'gem build paperclip.gemspec'
84
57
  end
85
58
 
86
59
  desc "Print a list of the files to be put into the gem"
@@ -89,13 +62,13 @@ task :manifest => :clean do
89
62
  puts file
90
63
  end
91
64
  end
92
-
65
+
93
66
  desc "Generate a gemspec file for GitHub"
94
67
  task :gemspec => :clean do
95
68
  File.open("#{spec.name}.gemspec", 'w') do |f|
96
69
  f.write spec.to_ruby
97
70
  end
98
- end
71
+ end
99
72
 
100
73
  desc "Build the gem into the current directory"
101
74
  task :gem => :gemspec do
@@ -1,5 +1,5 @@
1
1
  Usage:
2
2
 
3
3
  script/generate paperclip Class attachment1 (attachment2 ...)
4
-
5
- This will create a migration that will add the proper columns to your class's table.
4
+
5
+ This will create a migration that will add the proper columns to your class's table.
@@ -1,12 +1,12 @@
1
1
  class PaperclipGenerator < Rails::Generator::NamedBase
2
2
  attr_accessor :attachments, :migration_name
3
-
3
+
4
4
  def initialize(args, options = {})
5
5
  super
6
6
  @class_name, @attachments = args[0], args[1..-1]
7
7
  end
8
-
9
- def manifest
8
+
9
+ def manifest
10
10
  file_name = generate_file_name
11
11
  @migration_name = file_name.camelize
12
12
  record do |m|
@@ -14,14 +14,14 @@ class PaperclipGenerator < Rails::Generator::NamedBase
14
14
  File.join('db', 'migrate'),
15
15
  :migration_file_name => file_name
16
16
  end
17
- end
18
-
19
- private
20
-
17
+ end
18
+
19
+ private
20
+
21
21
  def generate_file_name
22
22
  names = attachments.map{|a| a.underscore }
23
23
  names = names[0..-2] + ["and", names[-1]] if names.length > 1
24
24
  "add_attachments_#{names.join("_")}_to_#{@class_name.underscore}"
25
25
  end
26
-
26
+
27
27
  end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate paperclip Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,31 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ class PaperclipGenerator < ActiveRecord::Generators::Base
4
+ desc "Create a migration to add paperclip-specific fields to your model."
5
+
6
+ argument :attachment_names, :required => true, :type => :array, :desc => "The names of the attachment(s) to add.",
7
+ :banner => "attachment_one attachment_two attachment_three ..."
8
+
9
+ def self.source_root
10
+ @source_root ||= File.expand_path('../templates', __FILE__)
11
+ end
12
+
13
+ def generate_migration
14
+ migration_template "paperclip_migration.rb.erb", "db/migrate/#{migration_file_name}"
15
+ end
16
+
17
+ protected
18
+
19
+ def migration_name
20
+ "add_attachment_#{attachment_names.join("_")}_to_#{name.underscore}"
21
+ end
22
+
23
+ def migration_file_name
24
+ "#{migration_name}.rb"
25
+ end
26
+
27
+ def migration_class_name
28
+ migration_name.camelize
29
+ end
30
+
31
+ end
@@ -0,0 +1,19 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ <% attachment_names.each do |attachment| -%>
4
+ add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_name, :string
5
+ add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_content_type, :string
6
+ add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_size, :integer
7
+ add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at, :datetime
8
+ <% end -%>
9
+ end
10
+
11
+ def self.down
12
+ <% attachment_names.each do |attachment| -%>
13
+ remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_name
14
+ remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_content_type
15
+ remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_size
16
+ remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at
17
+ <% end -%>
18
+ end
19
+ end
@@ -27,6 +27,7 @@
27
27
 
28
28
  require 'erb'
29
29
  require 'tempfile'
30
+ require 'paperclip/version'
30
31
  require 'paperclip/upfile'
31
32
  require 'paperclip/iostream'
32
33
  require 'paperclip/geometry'
@@ -34,9 +35,12 @@ require 'paperclip/processor'
34
35
  require 'paperclip/thumbnail'
35
36
  require 'paperclip/storage'
36
37
  require 'paperclip/interpolations'
38
+ require 'paperclip/style'
37
39
  require 'paperclip/attachment'
38
- if defined? RAILS_ROOT
39
- Dir.glob(File.join(File.expand_path(RAILS_ROOT), "lib", "paperclip_processors", "*.rb")).each do |processor|
40
+ require 'paperclip/callback_compatability'
41
+ require 'paperclip/railtie'
42
+ if defined?(Rails.root) && Rails.root
43
+ Dir.glob(File.join(File.expand_path(Rails.root), "lib", "paperclip_processors", "*.rb")).each do |processor|
40
44
  require processor
41
45
  end
42
46
  end
@@ -45,16 +49,14 @@ end
45
49
  # documentation for Paperclip::ClassMethods for more useful information.
46
50
  module Paperclip
47
51
 
48
- VERSION = "2.3.1.1"
49
-
50
52
  class << self
51
53
  # Provides configurability to Paperclip. There are a number of options available, such as:
52
- # * whiny: Will raise an error if Paperclip cannot process thumbnails of
54
+ # * whiny: Will raise an error if Paperclip cannot process thumbnails of
53
55
  # an uploaded image. Defaults to true.
54
56
  # * log: Logs progress to the Rails log. Uses ActiveRecord's logger, so honors
55
57
  # log levels, etc. Defaults to true.
56
58
  # * command_path: Defines the path at which to find the command line
57
- # programs if they are not visible to Rails the system's search path. Defaults to
59
+ # programs if they are not visible to Rails the system's search path. Defaults to
58
60
  # nil, which uses the first executable found in the user's search path.
59
61
  # * image_magick_path: Deprecated alias of command_path.
60
62
  def options
@@ -63,11 +65,15 @@ module Paperclip
63
65
  :image_magick_path => nil,
64
66
  :command_path => nil,
65
67
  :log => true,
66
- :log_command => false,
68
+ :log_command => true,
67
69
  :swallow_stderr => true
68
70
  }
69
71
  end
70
72
 
73
+ def configure
74
+ yield(self) if block_given?
75
+ end
76
+
71
77
  def path_for_command command #:nodoc:
72
78
  if options[:image_magick_path]
73
79
  warn("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
@@ -80,7 +86,7 @@ module Paperclip
80
86
  Paperclip::Interpolations[key] = block
81
87
  end
82
88
 
83
- # The run method takes a command to execute and a string of parameters
89
+ # The run method takes a command to execute and an array of parameters
84
90
  # that get passed to it. The command is prefixed with the :command_path
85
91
  # option from Paperclip.options. If you have many commands to run and
86
92
  # they are in different paths, the suggested course of action is to
@@ -89,29 +95,55 @@ module Paperclip
89
95
  # If the command returns with a result code that is not one of the
90
96
  # expected_outcodes, a PaperclipCommandLineError will be raised. Generally
91
97
  # a code of 0 is expected, but a list of codes may be passed if necessary.
98
+ # These codes should be passed as a hash as the last argument, like so:
92
99
  #
93
- # This method can log the command being run when
100
+ # Paperclip.run("echo", "something", :expected_outcodes => [0,1,2,3])
101
+ #
102
+ # This method can log the command being run when
94
103
  # Paperclip.options[:log_command] is set to true (defaults to false). This
95
104
  # will only log if logging in general is set to true as well.
96
- def run cmd, params = "", expected_outcodes = 0
97
- command = %Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ")
105
+ def run cmd, *params
106
+ options = params.last.is_a?(Hash) ? params.pop : {}
107
+ expected_outcodes = options[:expected_outcodes] || [0]
108
+ params = quote_command_options(*params).join(" ")
109
+
110
+ command = %Q[#{path_for_command(cmd)} #{params}]
98
111
  command = "#{command} 2>#{bit_bucket}" if Paperclip.options[:swallow_stderr]
99
112
  Paperclip.log(command) if Paperclip.options[:log_command]
100
- output = `#{command}`
101
- unless [expected_outcodes].flatten.include?($?.exitstatus)
102
- raise PaperclipCommandLineError, "Error while running #{cmd}"
113
+
114
+ begin
115
+ output = `#{command}`
116
+
117
+ raise CommandNotFoundError if $?.exitstatus == 127
118
+
119
+ unless expected_outcodes.include?($?.exitstatus)
120
+ raise PaperclipCommandLineError,
121
+ "Error while running #{cmd}. Expected return code to be #{expected_outcodes.join(", ")} but was #{$?.exitstatus}",
122
+ output
123
+ end
124
+ rescue Errno::ENOENT => e
125
+ raise CommandNotFoundError
103
126
  end
127
+
104
128
  output
105
129
  end
106
130
 
131
+ def quote_command_options(*options)
132
+ options.map do |option|
133
+ option.split("'").map{|m| "'#{m}'" }.join("\\'")
134
+ end
135
+ end
136
+
107
137
  def bit_bucket #:nodoc:
108
138
  File.exists?("/dev/null") ? "/dev/null" : "NUL"
109
139
  end
110
140
 
111
141
  def included base #:nodoc:
112
142
  base.extend ClassMethods
113
- unless base.respond_to?(:define_callbacks)
114
- base.send(:include, Paperclip::CallbackCompatability)
143
+ if base.respond_to?("set_callback")
144
+ base.send :include, Paperclip::CallbackCompatability::Rails3
145
+ else
146
+ base.send :include, Paperclip::CallbackCompatability::Rails21
115
147
  end
116
148
  end
117
149
 
@@ -119,7 +151,7 @@ module Paperclip
119
151
  name = name.to_s.camelize
120
152
  processor = Paperclip.const_get(name)
121
153
  unless processor.ancestors.include?(Paperclip::Processor)
122
- raise PaperclipError.new("Processor #{name} was not found")
154
+ raise PaperclipError.new("Processor #{name} was not found")
123
155
  end
124
156
  processor
125
157
  end
@@ -142,56 +174,64 @@ module Paperclip
142
174
  class PaperclipError < StandardError #:nodoc:
143
175
  end
144
176
 
145
- class PaperclipCommandLineError < StandardError #:nodoc:
177
+ class PaperclipCommandLineError < PaperclipError #:nodoc:
178
+ attr_accessor :output
179
+ def initialize(msg = nil, output = nil)
180
+ super(msg)
181
+ @output = output
182
+ end
183
+ end
184
+
185
+ class CommandNotFoundError < PaperclipError
146
186
  end
147
187
 
148
188
  class NotIdentifiedByImageMagickError < PaperclipError #:nodoc:
149
189
  end
150
-
190
+
151
191
  class InfiniteInterpolationError < PaperclipError #:nodoc:
152
192
  end
153
193
 
154
194
  module ClassMethods
155
195
  # +has_attached_file+ gives the class it is called on an attribute that maps to a file. This
156
- # is typically a file stored somewhere on the filesystem and has been uploaded by a user.
196
+ # is typically a file stored somewhere on the filesystem and has been uploaded by a user.
157
197
  # The attribute returns a Paperclip::Attachment object which handles the management of
158
- # that file. The intent is to make the attachment as much like a normal attribute. The
159
- # thumbnails will be created when the new file is assigned, but they will *not* be saved
160
- # until +save+ is called on the record. Likewise, if the attribute is set to +nil+ is
161
- # called on it, the attachment will *not* be deleted until +save+ is called. See the
162
- # Paperclip::Attachment documentation for more specifics. There are a number of options
198
+ # that file. The intent is to make the attachment as much like a normal attribute. The
199
+ # thumbnails will be created when the new file is assigned, but they will *not* be saved
200
+ # until +save+ is called on the record. Likewise, if the attribute is set to +nil+ is
201
+ # called on it, the attachment will *not* be deleted until +save+ is called. See the
202
+ # Paperclip::Attachment documentation for more specifics. There are a number of options
163
203
  # you can set to change the behavior of a Paperclip attachment:
164
204
  # * +url+: The full URL of where the attachment is publically accessible. This can just
165
205
  # as easily point to a directory served directly through Apache as it can to an action
166
206
  # that can control permissions. You can specify the full domain and path, but usually
167
- # just an absolute path is sufficient. The leading slash *must* be included manually for
168
- # absolute paths. The default value is
207
+ # just an absolute path is sufficient. The leading slash *must* be included manually for
208
+ # absolute paths. The default value is
169
209
  # "/system/:attachment/:id/:style/:filename". See
170
210
  # Paperclip::Attachment#interpolate for more information on variable interpolaton.
171
211
  # :url => "/:class/:attachment/:id/:style_:filename"
172
212
  # :url => "http://some.other.host/stuff/:class/:id_:extension"
173
- # * +default_url+: The URL that will be returned if there is no attachment assigned.
174
- # This field is interpolated just as the url is. The default value is
213
+ # * +default_url+: The URL that will be returned if there is no attachment assigned.
214
+ # This field is interpolated just as the url is. The default value is
175
215
  # "/:attachment/:style/missing.png"
176
216
  # has_attached_file :avatar, :default_url => "/images/default_:style_avatar.png"
177
217
  # User.new.avatar_url(:small) # => "/images/default_small_avatar.png"
178
- # * +styles+: A hash of thumbnail styles and their geometries. You can find more about
179
- # geometry strings at the ImageMagick website
218
+ # * +styles+: A hash of thumbnail styles and their geometries. You can find more about
219
+ # geometry strings at the ImageMagick website
180
220
  # (http://www.imagemagick.org/script/command-line-options.php#resize). Paperclip
181
- # also adds the "#" option (e.g. "50x50#"), which will resize the image to fit maximally
182
- # inside the dimensions and then crop the rest off (weighted at the center). The
221
+ # also adds the "#" option (e.g. "50x50#"), which will resize the image to fit maximally
222
+ # inside the dimensions and then crop the rest off (weighted at the center). The
183
223
  # default value is to generate no thumbnails.
184
- # * +default_style+: The thumbnail style that will be used by default URLs.
224
+ # * +default_style+: The thumbnail style that will be used by default URLs.
185
225
  # Defaults to +original+.
186
226
  # has_attached_file :avatar, :styles => { :normal => "100x100#" },
187
227
  # :default_style => :normal
188
228
  # user.avatar.url # => "/avatars/23/normal_me.png"
189
229
  # * +whiny+: Will raise an error if Paperclip cannot post_process an uploaded file due
190
- # to a command line error. This will override the global setting for this attachment.
230
+ # to a command line error. This will override the global setting for this attachment.
191
231
  # Defaults to true. This option used to be called :whiny_thumbanils, but this is
192
232
  # deprecated.
193
233
  # * +convert_options+: When creating thumbnails, use this free-form options
194
- # field to pass in various convert command options. Typical options are "-strip" to
234
+ # array to pass in various convert command options. Typical options are "-strip" to
195
235
  # remove all Exif data from the image (save space for thumbnails and avatars) or
196
236
  # "-depth 8" to specify the bit depth of the resulting conversion. See ImageMagick
197
237
  # convert documentation for more options: (http://www.imagemagick.org/script/convert.php)
@@ -208,6 +248,9 @@ module Paperclip
208
248
  # NOTE: While not deprecated yet, it is not recommended to specify options this way.
209
249
  # It is recommended that :convert_options option be included in the hash passed to each
210
250
  # :styles for compatability with future versions.
251
+ # NOTE: Strings supplied to :convert_options are split on space in order to undergo
252
+ # shell quoting for safety. If your options require a space, please pre-split them
253
+ # and pass an array to :convert_options instead.
211
254
  # * +storage+: Chooses the storage backend where the files will be stored. The current
212
255
  # choices are :filesystem and :s3. The default is :filesystem. Make sure you read the
213
256
  # documentation for Paperclip::Storage::Filesystem and Paperclip::Storage::S3
@@ -221,9 +264,8 @@ module Paperclip
221
264
  after_save :save_attached_files
222
265
  before_destroy :destroy_attached_files
223
266
 
224
- define_callbacks :before_post_process, :after_post_process
225
- define_callbacks :"before_#{name}_post_process", :"after_#{name}_post_process"
226
-
267
+ define_paperclip_callbacks :post_process, :"#{name}_post_process"
268
+
227
269
  define_method name do |*args|
228
270
  a = attachment_for(name)
229
271
  (args.length > 0) ? a.to_s(args.first) : a
@@ -239,7 +281,7 @@ module Paperclip
239
281
 
240
282
  validates_each(name) do |record, attr, value|
241
283
  attachment = record.attachment_for(name)
242
- attachment.send(:flush_errors) unless attachment.valid?
284
+ attachment.send(:flush_errors)
243
285
  end
244
286
  end
245
287
 
@@ -257,13 +299,13 @@ module Paperclip
257
299
  max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
258
300
  range = (min..max)
259
301
  message = options[:message] || "file size must be between :min and :max bytes."
302
+ message = message.gsub(/:min/, min.to_s).gsub(/:max/, max.to_s)
260
303
 
261
- attachment_definitions[name][:validations] << [:size, {:min => min,
262
- :max => max,
263
- :range => range,
264
- :message => message,
265
- :if => options[:if],
266
- :unless => options[:unless]}]
304
+ validates_inclusion_of :"#{name}_file_size",
305
+ :in => range,
306
+ :message => message,
307
+ :if => options[:if],
308
+ :unless => options[:unless]
267
309
  end
268
310
 
269
311
  # Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
@@ -281,18 +323,19 @@ module Paperclip
281
323
  # * +unless+: Same as +if+ but validates if lambda or method returns false.
282
324
  def validates_attachment_presence name, options = {}
283
325
  message = options[:message] || "must be set."
284
- attachment_definitions[name][:validations] << [:presence, {:message => message,
285
- :if => options[:if],
286
- :unless => options[:unless]}]
326
+ validates_presence_of :"#{name}_file_name",
327
+ :message => message,
328
+ :if => options[:if],
329
+ :unless => options[:unless]
287
330
  end
288
-
331
+
289
332
  # Places ActiveRecord-style validations on the content type of the file
290
- # assigned. The possible options are:
291
- # * +content_type+: Allowed content types. Can be a single content type
292
- # or an array. Each type can be a String or a Regexp. It should be
293
- # noted that Internet Explorer upload files with content_types that you
294
- # may not expect. For example, JPEG images are given image/pjpeg and
295
- # PNGs are image/x-png, so keep that in mind when determining how you
333
+ # assigned. The possible options are:
334
+ # * +content_type+: Allowed content types. Can be a single content type
335
+ # or an array. Each type can be a String or a Regexp. It should be
336
+ # noted that Internet Explorer upload files with content_types that you
337
+ # may not expect. For example, JPEG images are given image/pjpeg and
338
+ # PNGs are image/x-png, so keep that in mind when determining how you
296
339
  # match. Allows all by default.
297
340
  # * +message+: The message to display when the uploaded file has an invalid
298
341
  # content type.
@@ -303,10 +346,17 @@ module Paperclip
303
346
  # model, content_type validation will work _ONLY upon assignment_ and
304
347
  # re-validation after the instance has been reloaded will always succeed.
305
348
  def validates_attachment_content_type name, options = {}
306
- attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
307
- :message => options[:message],
308
- :if => options[:if],
309
- :unless => options[:unless]}]
349
+ types = [options.delete(:content_type)].flatten
350
+ validates_each(:"#{name}_content_type", options) do |record, attr, value|
351
+ unless types.any?{|t| t === value }
352
+ if record.errors.method(:add).arity == -2
353
+ message = options[:message] || "is not one of #{types.join(", ")}"
354
+ record.errors.add(:"#{name}_content_type", message)
355
+ else
356
+ record.errors.add(:"#{name}_content_type", :inclusion, :default => options[:message], :value => value)
357
+ end
358
+ end
359
+ end
310
360
  end
311
361
 
312
362
  # Returns the attachment definitions defined by each call to
@@ -321,7 +371,7 @@ module Paperclip
321
371
  @_paperclip_attachments ||= {}
322
372
  @_paperclip_attachments[name] ||= Attachment.new(name, self, self.class.attachment_definitions[name])
323
373
  end
324
-
374
+
325
375
  def each_attachment
326
376
  self.class.attachment_definitions.each do |name, definition|
327
377
  yield(name, attachment_for(name))
@@ -329,14 +379,14 @@ module Paperclip
329
379
  end
330
380
 
331
381
  def save_attached_files
332
- logger.info("[paperclip] Saving attachments.")
382
+ Paperclip.log("Saving attachments.")
333
383
  each_attachment do |name, attachment|
334
384
  attachment.send(:save)
335
385
  end
336
386
  end
337
387
 
338
388
  def destroy_attached_files
339
- logger.info("[paperclip] Deleting attachments.")
389
+ Paperclip.log("Deleting attachments.")
340
390
  each_attachment do |name, attachment|
341
391
  attachment.send(:queue_existing_for_delete)
342
392
  attachment.send(:flush_deletes)
@@ -345,9 +395,3 @@ module Paperclip
345
395
  end
346
396
 
347
397
  end
348
-
349
- # Set it all up.
350
- if Object.const_defined?("ActiveRecord")
351
- ActiveRecord::Base.send(:include, Paperclip)
352
- File.send(:include, Paperclip::Upfile)
353
- end