carrierwave 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of carrierwave might be problematic. Click here for more details.

@@ -3,6 +3,12 @@
3
3
  require 'fileutils'
4
4
  require 'active_support/core_ext/object/blank'
5
5
  require 'active_support/core_ext/class/attribute'
6
+
7
+ begin
8
+ require 'active_support/core_ext/class/inheritable_attributes'
9
+ rescue LoadError
10
+ end
11
+
6
12
  require 'active_support/concern'
7
13
  require 'active_support/memoizable'
8
14
 
@@ -31,6 +37,7 @@ module CarrierWave
31
37
  autoload :RMagick, 'carrierwave/processing/rmagick'
32
38
  autoload :ImageScience, 'carrierwave/processing/image_science'
33
39
  autoload :MiniMagick, 'carrierwave/processing/mini_magick'
40
+ autoload :MimeTypes, 'carrierwave/processing/mime_types'
34
41
  autoload :VERSION, 'carrierwave/version'
35
42
 
36
43
  module Storage
@@ -65,10 +65,11 @@ module CarrierWave
65
65
  # @user.image.url # => '/some_url.png'
66
66
  #
67
67
  # It is also possible (but not recommended) to ommit the uploader, which
68
- # will create an anonymous uploader class. Passing a block to this method
69
- # makes it possible to customize it. This can be convenient for brevity,
70
- # but if there is any significatnt logic in the uploader, you should do
71
- # the right thing and have it in its own file.
68
+ # will create an anonymous uploader class.
69
+ #
70
+ # Passing a block makes it possible to customize the uploader. This can be
71
+ # convenient for brevity, but if there is any significatnt logic in the
72
+ # uploader, you should do the right thing and have it in its own file.
72
73
  #
73
74
  # === Added instance methods
74
75
  #
@@ -97,6 +98,7 @@ module CarrierWave
97
98
  # [image_processing_error] Returns an error object if the last file to be assigned caused a processing error
98
99
  #
99
100
  # [write_image_identifier] Uses the write_uploader method to set the identifier.
101
+ # [image_identifier] Reads out the identifier of the file
100
102
  #
101
103
  # === Parameters
102
104
  #
@@ -138,9 +140,12 @@ module CarrierWave
138
140
  # end
139
141
  #
140
142
  def mount_uploader(column, uploader=nil, options={}, &block)
141
- unless uploader
142
- uploader = Class.new(CarrierWave::Uploader::Base)
143
+ if block_given?
144
+ uploader = Class.new(uploader || CarrierWave::Uploader::Base)
143
145
  uploader.class_eval(&block)
146
+ uploader.recursively_apply_block_to_versions(&block)
147
+ else
148
+ uploader ||= Class.new(CarrierWave::Uploader::Base)
144
149
  end
145
150
 
146
151
  uploaders[column.to_sym] = uploader
@@ -226,8 +231,30 @@ module CarrierWave
226
231
  _mounter(:#{column}).write_identifier
227
232
  end
228
233
 
229
- RUBY
234
+ def #{column}_identifier
235
+ _mounter(:#{column}).identifier
236
+ end
237
+
238
+ def store_previous_model_for_#{column}
239
+ serialization_column = _mounter(:#{column}).serialization_column
240
+
241
+ if #{column}.remove_previously_stored_files_after_update && send(:"\#{serialization_column}_changed?")
242
+ @previous_model_for_#{column} ||= self.find_previous_model_for_#{column}
243
+ end
244
+ end
245
+
246
+ def find_previous_model_for_#{column}
247
+ self.class.find(to_key.first)
248
+ end
249
+
250
+ def remove_previously_stored_#{column}
251
+ if @previous_model_for_#{column} && @previous_model_for_#{column}.#{column}.path != #{column}.path
252
+ @previous_model_for_#{column}.#{column}.remove!
253
+ @previous_model_for_#{column} = nil
254
+ end
255
+ end
230
256
 
257
+ RUBY
231
258
  end
232
259
 
233
260
  module Extension
@@ -342,6 +369,10 @@ module CarrierWave
342
369
  uploader.remove!
343
370
  end
344
371
 
372
+ def serialization_column
373
+ option(:mount_on) || column
374
+ end
375
+
345
376
  private
346
377
 
347
378
  def option(name)
@@ -349,10 +380,6 @@ module CarrierWave
349
380
  end
350
381
  memoize :option
351
382
 
352
- def serialization_column
353
- option(:mount_on) || column
354
- end
355
-
356
383
  end # Mounter
357
384
 
358
385
  end # Mount
@@ -11,7 +11,7 @@ module CarrierWave
11
11
  ##
12
12
  # See +CarrierWave::Mount#mount_uploader+ for documentation
13
13
  #
14
- def mount_uploader(column, uploader, options={}, &block)
14
+ def mount_uploader(column, uploader=nil, options={}, &block)
15
15
  super
16
16
 
17
17
  alias_method :read_uploader, :read_attribute
@@ -27,10 +27,13 @@ module CarrierWave
27
27
  after_save :"store_#{column}!"
28
28
  before_save :"write_#{column}_identifier"
29
29
  after_destroy :"remove_#{column}!"
30
+ before_update :"store_previous_model_for_#{column}"
31
+ after_save :"remove_previously_stored_#{column}"
30
32
 
31
33
  class_eval <<-RUBY, __FILE__, __LINE__+1
32
34
  def #{column}=(new_file)
33
- #{column}_will_change!
35
+ column = _mounter(:#{column}).serialization_column
36
+ send(:"\#{column}_will_change!")
34
37
  super
35
38
  end
36
39
  RUBY
@@ -9,7 +9,7 @@ module CarrierWave
9
9
  ##
10
10
  # See +CarrierWave::Mount#mount_uploader+ for documentation
11
11
  #
12
- def mount_uploader(column, uploader, options={}, &block)
12
+ def mount_uploader(column, uploader=nil, options={}, &block)
13
13
  options[:mount_on] ||= "#{column}_filename"
14
14
  field options[:mount_on]
15
15
 
@@ -23,11 +23,46 @@ module CarrierWave
23
23
  validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
24
24
  validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
25
25
 
26
- after_save "store_#{column}!".to_sym
27
- before_save "write_#{column}_identifier".to_sym
28
- after_destroy "remove_#{column}!".to_sym
26
+ after_save :"store_#{column}!"
27
+ before_save :"write_#{column}_identifier"
28
+ after_destroy :"remove_#{column}!"
29
+ before_update :"store_previous_model_for_#{column}"
30
+ after_save :"remove_previously_stored_#{column}"
31
+
32
+ class_eval <<-RUBY, __FILE__, __LINE__+1
33
+ def #{column}=(new_file)
34
+ column = _mounter(:#{column}).serialization_column
35
+
36
+ # Note (Didier L.): equivalent of the <column>_will_change! ActiveModel method
37
+ begin
38
+ value = __send__(column)
39
+ value = value.duplicable? ? value.clone : value
40
+ rescue TypeError, NoMethodError
41
+ end
42
+ setup_modifications
43
+
44
+ super.tap do
45
+ @modifications[column] = [value, __send__(column)]
46
+ end
47
+ end
48
+
49
+ def #{column}_changed?
50
+ column = _mounter(:#{column}).serialization_column
51
+ send(:"\#{column}_changed?")
52
+ end
53
+
54
+ def find_previous_model_for_#{column}
55
+ if self.embedded?
56
+ self._parent.reload.send(self.metadata.key).find(to_key.first)
57
+ else
58
+ self.class.find(to_key.first)
59
+ end
60
+ end
61
+
62
+ RUBY
63
+
29
64
  end
30
65
  end # Mongoid
31
66
  end # CarrierWave
32
67
 
33
- Mongoid::Document::ClassMethods.send(:include, CarrierWave::Mongoid)
68
+ Mongoid::Document::ClassMethods.send(:include, CarrierWave::Mongoid)
@@ -26,8 +26,6 @@ module CarrierWave
26
26
  # specified in the smaller dimension but will not be larger than the
27
27
  # specified values.
28
28
  #
29
- # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
30
- #
31
29
  # === Parameters
32
30
  #
33
31
  # [width (Integer)] the width to scale the image to
@@ -49,8 +47,6 @@ module CarrierWave
49
47
  # the aspect ratio of the original image. If necessary, crop the image in
50
48
  # the larger dimension.
51
49
  #
52
- # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
53
- #
54
50
  # === Parameters
55
51
  #
56
52
  # [width (Integer)] the width to scale the image to
@@ -0,0 +1,58 @@
1
+ require 'mime/types'
2
+
3
+ module CarrierWave
4
+
5
+ ##
6
+ # This module simplifies the use of the mime-types gem to intelligently
7
+ # guess and set the content-type of a file. If you want to use this, you'll
8
+ # need to require this file:
9
+ #
10
+ # require 'carrierwave/processing/mime_types'
11
+ #
12
+ # And then include it in your uploader:
13
+ #
14
+ # class MyUploader < CarrierWave::Uploader::Base
15
+ # include CarrierWave::MimeTypes
16
+ # end
17
+ #
18
+ # You can now use the provided helper:
19
+ #
20
+ # class MyUploader < CarrierWave::Uploader::Base
21
+ # include CarrierWave::MimeTypes
22
+ #
23
+ # process :set_content_type
24
+ # end
25
+ #
26
+ module MimeTypes
27
+ extend ActiveSupport::Concern
28
+
29
+ module ClassMethods
30
+ def set_content_type(override=false)
31
+ process :set_content_type => override
32
+ end
33
+ end
34
+
35
+ ##
36
+ # Changes the file content_type using the mime-types gem
37
+ #
38
+ # === Parameters
39
+ #
40
+ # [override (Boolean)] whether or not to override the file's content_type
41
+ # if it is already set and not a generic content-type,
42
+ # false by default
43
+ #
44
+ def set_content_type(override=false)
45
+ if override || file.content_type.blank? || file.content_type == 'application/octet-stream'
46
+ new_content_type = ::MIME::Types.type_for(file.original_filename).first.to_s
47
+ if file.respond_to?(:content_type=)
48
+ file.content_type = new_content_type
49
+ else
50
+ file.set_instance_variable(:@content_type, new_content_type)
51
+ end
52
+ end
53
+ rescue ::MIME::InvalidContentType => e
54
+ raise CarrierWave::ProcessingError.new("Failed to process file with MIME::Types, maybe not valid content-type? Original Error: #{e}")
55
+ end
56
+
57
+ end # MimeTypes
58
+ end # CarrierWave
@@ -129,12 +129,9 @@ module CarrierWave
129
129
  end
130
130
 
131
131
  ##
132
- # From the RMagick documentation: "Resize the image to fit within the
133
- # specified dimensions while retaining the original aspect ratio. The
134
- # image may be shorter or narrower than specified in the smaller dimension
135
- # but will not be larger than the specified values."
136
- #
137
- # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
132
+ # Resize the image to fit within the specified dimensions while retaining
133
+ # the original aspect ratio. The image may be shorter or narrower than
134
+ # specified in the smaller dimension but will not be larger than the specified values.
138
135
  #
139
136
  # === Parameters
140
137
  #
@@ -154,15 +151,9 @@ module CarrierWave
154
151
  end
155
152
 
156
153
  ##
157
- # From the RMagick documentation: "Resize the image to fit within the
158
- # specified dimensions while retaining the aspect ratio of the original
159
- # image. If necessary, crop the image in the larger dimension."
160
- #
161
- # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
162
- #
163
- # and
164
- #
165
- # http://www.clipclip.org/clips/detail/4365/jerrett-net-»-crop_resized-in-rmagick
154
+ # Resize the image to fit within the specified dimensions while retaining
155
+ # the aspect ratio of the original image. If necessary, crop the image in the
156
+ # larger dimension.
166
157
  #
167
158
  # === Parameters
168
159
  #
@@ -229,7 +220,7 @@ module CarrierWave
229
220
  end
230
221
 
231
222
  ##
232
- # Manipulate the image with RMagick. This method will load up an image
223
+ # Manipulate the image with MiniMagick. This method will load up an image
233
224
  # and then pass each of its frames to the supplied block. It will then
234
225
  # save the image to disk.
235
226
  #
@@ -17,6 +17,14 @@ module CarrierWave
17
17
 
18
18
  attr_accessor :file
19
19
 
20
+ class << self
21
+ attr_writer :sanitize_regexp
22
+
23
+ def sanitize_regexp
24
+ @sanitize_regexp ||= /[^a-zA-Z0-9\.\-\+_]/
25
+ end
26
+ end
27
+
20
28
  def initialize(file)
21
29
  self.file = file
22
30
  end
@@ -127,8 +135,6 @@ module CarrierWave
127
135
  @file.nil? || self.size.nil? || self.size.zero?
128
136
  end
129
137
 
130
- alias_method :blank?, :empty?
131
-
132
138
  ##
133
139
  # === Returns
134
140
  #
@@ -222,6 +228,17 @@ module CarrierWave
222
228
  @file.content_type.chomp if @file.respond_to?(:content_type) and @file.content_type
223
229
  end
224
230
 
231
+ ##
232
+ # Sets the content type of the file.
233
+ #
234
+ # === Returns
235
+ #
236
+ # [String] the content type of the file
237
+ #
238
+ def content_type=(type)
239
+ @content_type = type
240
+ end
241
+
225
242
  ##
226
243
  # Used to sanitize the file name. Public to allow overriding for non-latin characters.
227
244
  #
@@ -230,7 +247,7 @@ module CarrierWave
230
247
  # [Regexp] the regexp for sanitizing the file name
231
248
  #
232
249
  def sanitize_regexp
233
- /[^a-zA-Z0-9\.\-\+_]/
250
+ CarrierWave::SanitizedFile.sanitize_regexp
234
251
  end
235
252
 
236
253
  private
@@ -263,7 +280,7 @@ module CarrierWave
263
280
  name = name.gsub(sanitize_regexp,"_")
264
281
  name = "_#{name}" if name =~ /\A\.+\z/
265
282
  name = "unnamed" if name.size == 0
266
- return name.mb_chars.downcase.to_s
283
+ return name.mb_chars.to_s
267
284
  end
268
285
 
269
286
  def split_extension(filename)
@@ -41,11 +41,11 @@ module CarrierWave
41
41
  # This only works as long as you haven't done anything funky with your cache_dir.
42
42
  # It's recommended that you keep cache files in one place only.
43
43
  #
44
- def clean_cached_files!
44
+ def clean_cached_files!(seconds=60*60*24)
45
45
  Dir.glob(File.expand_path(File.join(cache_dir, '*'), CarrierWave.root)).each do |dir|
46
46
  time = dir.scan(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/).first.map { |t| t.to_i }
47
47
  time = Time.utc(*time)
48
- if time < (Time.now.utc - (60*60*24))
48
+ if time < (Time.now.utc - seconds)
49
49
  FileUtils.rm_rf(dir)
50
50
  end
51
51
  end
@@ -130,7 +130,16 @@ module CarrierWave
130
130
  with_callbacks(:retrieve_from_cache, cache_name) do
131
131
  self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
132
132
  @filename = original_filename
133
- @file = CarrierWave::SanitizedFile.new(cache_path)
133
+
134
+ if File.exist?(cache_path) && defined?(MIME::Types)
135
+ @file = SanitizedFile.new(
136
+ :tempfile => cache_path,
137
+ :filename => @filename,
138
+ :content_type => MIME::Types.of(File.basename(cache_path))[0].content_type
139
+ )
140
+ else
141
+ @file = CarrierWave::SanitizedFile.new(cache_path)
142
+ end
134
143
  end
135
144
  end
136
145
 
@@ -151,7 +160,7 @@ module CarrierWave
151
160
  end
152
161
 
153
162
  def original_filename=(filename)
154
- raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /\A[a-z0-9\.\-\+_]+\z/i
163
+ raise CarrierWave::InvalidParameter, "invalid filename" if filename =~ CarrierWave::SanitizedFile.sanitize_regexp
155
164
  @original_filename = filename
156
165
  end
157
166
 
@@ -5,6 +5,8 @@ module CarrierWave
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
+ class_attribute :_storage, :instance_writer => false
9
+
8
10
  add_config :root
9
11
  add_config :permissions
10
12
  add_config :storage_engines
@@ -35,6 +37,8 @@ module CarrierWave
35
37
  add_config :enable_processing
36
38
  add_config :ensure_multipart_form
37
39
  add_config :delete_tmp_file_after_storage
40
+ add_config :delete_cache_id_after_storage
41
+ add_config :remove_previously_stored_files_after_update
38
42
 
39
43
  # fog
40
44
  add_config :fog_attributes
@@ -81,19 +85,13 @@ module CarrierWave
81
85
  # storage MyCustomStorageEngine
82
86
  #
83
87
  def storage(storage = nil)
84
- if storage.is_a?(Symbol)
85
- @storage = eval(storage_engines[storage])
86
- elsif storage
87
- @storage = storage
88
- elsif @storage.nil?
89
- # Get the storage from the superclass if there is one
90
- @storage = superclass.storage rescue nil
88
+ if storage
89
+ self._storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
91
90
  end
92
- return @storage
91
+ _storage
93
92
  end
94
93
  alias_method :storage=, :storage
95
94
 
96
-
97
95
  def add_config(name)
98
96
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
99
97
  def self.#{name}(value=nil)
@@ -147,6 +145,8 @@ module CarrierWave
147
145
  config.store_dir = 'uploads'
148
146
  config.cache_dir = 'uploads/tmp'
149
147
  config.delete_tmp_file_after_storage = true
148
+ config.delete_cache_id_after_storage = true
149
+ config.remove_previously_stored_files_after_update = true
150
150
  config.ignore_integrity_errors = true
151
151
  config.ignore_processing_errors = true
152
152
  config.validate_integrity = true