carrierwave 0.11.2 → 1.0.0.beta

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.

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +220 -116
  3. data/lib/carrierwave.rb +8 -10
  4. data/lib/carrierwave/compatibility/paperclip.rb +0 -2
  5. data/lib/carrierwave/error.rb +1 -0
  6. data/lib/carrierwave/locale/en.yml +7 -4
  7. data/lib/carrierwave/mount.rb +209 -176
  8. data/lib/carrierwave/mounter.rb +163 -0
  9. data/lib/carrierwave/orm/activerecord.rb +49 -20
  10. data/lib/carrierwave/processing.rb +0 -1
  11. data/lib/carrierwave/processing/mini_magick.rb +64 -13
  12. data/lib/carrierwave/processing/rmagick.rb +31 -3
  13. data/lib/carrierwave/sanitized_file.rb +43 -38
  14. data/lib/carrierwave/storage.rb +0 -9
  15. data/lib/carrierwave/storage/abstract.rb +15 -2
  16. data/lib/carrierwave/storage/file.rb +64 -2
  17. data/lib/carrierwave/storage/fog.rb +100 -27
  18. data/lib/carrierwave/test/matchers.rb +77 -12
  19. data/lib/carrierwave/uploader.rb +2 -2
  20. data/lib/carrierwave/uploader/cache.rb +40 -26
  21. data/lib/carrierwave/uploader/callbacks.rb +0 -2
  22. data/lib/carrierwave/uploader/configuration.rb +48 -6
  23. data/lib/carrierwave/uploader/default_url.rb +3 -5
  24. data/lib/carrierwave/uploader/download.rb +2 -4
  25. data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
  26. data/lib/carrierwave/uploader/extension_whitelist.rb +12 -10
  27. data/lib/carrierwave/uploader/file_size.rb +41 -0
  28. data/lib/carrierwave/uploader/magic_mime_blacklist.rb +94 -0
  29. data/lib/carrierwave/uploader/magic_mime_whitelist.rb +94 -0
  30. data/lib/carrierwave/uploader/mountable.rb +7 -8
  31. data/lib/carrierwave/uploader/processing.rb +1 -3
  32. data/lib/carrierwave/uploader/proxy.rb +5 -7
  33. data/lib/carrierwave/uploader/remove.rb +0 -2
  34. data/lib/carrierwave/uploader/serialization.rb +1 -3
  35. data/lib/carrierwave/uploader/store.rb +5 -23
  36. data/lib/carrierwave/uploader/url.rb +1 -3
  37. data/lib/carrierwave/uploader/versions.rb +75 -82
  38. data/lib/carrierwave/utilities.rb +0 -3
  39. data/lib/carrierwave/utilities/uri.rb +4 -7
  40. data/lib/carrierwave/validations/active_model.rb +0 -2
  41. data/lib/carrierwave/version.rb +1 -1
  42. data/lib/generators/templates/uploader.rb +3 -5
  43. metadata +43 -97
  44. data/lib/carrierwave/locale/cs.yml +0 -11
  45. data/lib/carrierwave/locale/de.yml +0 -11
  46. data/lib/carrierwave/locale/el.yml +0 -11
  47. data/lib/carrierwave/locale/es.yml +0 -11
  48. data/lib/carrierwave/locale/fr.yml +0 -11
  49. data/lib/carrierwave/locale/ja.yml +0 -11
  50. data/lib/carrierwave/locale/nb.yml +0 -11
  51. data/lib/carrierwave/locale/nl.yml +0 -11
  52. data/lib/carrierwave/locale/pl.yml +0 -11
  53. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  54. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  55. data/lib/carrierwave/locale/ru.yml +0 -11
  56. data/lib/carrierwave/locale/sk.yml +0 -11
  57. data/lib/carrierwave/locale/tr.yml +0 -11
  58. data/lib/carrierwave/processing/mime_types.rb +0 -74
  59. data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -0,0 +1,163 @@
1
+ module CarrierWave
2
+
3
+ # this is an internal class, used by CarrierWave::Mount so that
4
+ # we don't pollute the model with a lot of methods.
5
+ class Mounter #:nodoc:
6
+ attr_reader :column, :record, :remote_urls, :integrity_error, :processing_error, :download_error
7
+ attr_accessor :remove
8
+
9
+ def initialize(record, column, options={})
10
+ @record = record
11
+ @column = column
12
+ @options = record.class.uploader_options[column]
13
+ end
14
+
15
+ def uploader_class
16
+ record.class.uploaders[column]
17
+ end
18
+
19
+ def blank_uploader
20
+ uploader_class.new(record, column)
21
+ end
22
+
23
+ def identifiers
24
+ uploaders.map(&:identifier)
25
+ end
26
+
27
+ def read_identifiers
28
+ [record.read_uploader(serialization_column)].flatten.reject(&:blank?)
29
+ end
30
+
31
+ def uploaders
32
+ @uploaders ||= read_identifiers.map do |identifier|
33
+ uploader = blank_uploader
34
+ uploader.retrieve_from_store!(identifier) if identifier.present?
35
+ uploader
36
+ end
37
+ end
38
+
39
+ def cache(new_files)
40
+ return if not new_files or new_files == ""
41
+ @uploaders = new_files.map do |new_file|
42
+ uploader = blank_uploader
43
+ uploader.cache!(new_file)
44
+ uploader
45
+ end
46
+
47
+ @integrity_error = nil
48
+ @processing_error = nil
49
+ rescue CarrierWave::IntegrityError => e
50
+ @integrity_error = e
51
+ raise e unless option(:ignore_integrity_errors)
52
+ rescue CarrierWave::ProcessingError => e
53
+ @processing_error = e
54
+ raise e unless option(:ignore_processing_errors)
55
+ end
56
+
57
+ def cache_names
58
+ uploaders.map(&:cache_name).compact
59
+ end
60
+
61
+ def cache_names=(cache_names)
62
+ return if not cache_names or cache_names == "" or uploaders.any?(&:cached?)
63
+ @uploaders = cache_names.map do |cache_name|
64
+ uploader = blank_uploader
65
+ uploader.retrieve_from_cache!(cache_name)
66
+ uploader
67
+ end
68
+ rescue CarrierWave::InvalidParameter
69
+ end
70
+
71
+ def remote_urls=(urls)
72
+ return if not urls or urls == "" or urls.all?(&:blank?)
73
+
74
+ @remote_urls = urls
75
+ @download_error = nil
76
+ @integrity_error = nil
77
+
78
+ @uploaders = urls.map do |url|
79
+ uploader = blank_uploader
80
+ uploader.download!(url)
81
+ uploader
82
+ end
83
+
84
+ rescue CarrierWave::DownloadError => e
85
+ @download_error = e
86
+ raise e unless option(:ignore_download_errors)
87
+ rescue CarrierWave::ProcessingError => e
88
+ @processing_error = e
89
+ raise e unless option(:ignore_processing_errors)
90
+ rescue CarrierWave::IntegrityError => e
91
+ @integrity_error = e
92
+ raise e unless option(:ignore_integrity_errors)
93
+ end
94
+
95
+ def store!
96
+ if remove?
97
+ remove!
98
+ else
99
+ uploaders.reject(&:blank?).each(&:store!)
100
+ end
101
+ end
102
+
103
+ def urls(*args)
104
+ uploaders.map { |u| u.url(*args) }
105
+ end
106
+
107
+ def blank?
108
+ uploaders.none?(&:present?)
109
+ end
110
+
111
+ def remove?
112
+ remove.present? && remove !~ /\A0|false$\z/
113
+ end
114
+
115
+ def remove!
116
+ uploaders.reject(&:blank?).each(&:remove!)
117
+ @uploaders = []
118
+ end
119
+
120
+ def serialization_column
121
+ option(:mount_on) || column
122
+ end
123
+
124
+ def remove_previous(before=nil, after=nil)
125
+ return unless before
126
+
127
+ # both 'before' and 'after' can be string when 'mount_on' option is set
128
+ before = before.reject(&:blank?).map do |value|
129
+ if value.is_a?(String)
130
+ uploader = blank_uploader
131
+ uploader.retrieve_from_store!(value)
132
+ uploader
133
+ else
134
+ value
135
+ end
136
+ end
137
+ after_paths = after.reject(&:blank?).map do |value|
138
+ if value.is_a?(String)
139
+ uploader = blank_uploader
140
+ uploader.retrieve_from_store!(value)
141
+ uploader
142
+ else
143
+ value
144
+ end.path
145
+ end
146
+ before.each do |uploader|
147
+ if uploader.remove_previously_stored_files_after_update and not after_paths.include?(uploader.path)
148
+ uploader.remove!
149
+ end
150
+ end
151
+ end
152
+
153
+ attr_accessor :uploader_options
154
+
155
+ private
156
+
157
+ def option(name)
158
+ self.uploader_options ||= {}
159
+ self.uploader_options[name] ||= record.class.uploader_option(column, name)
160
+ end
161
+
162
+ end # Mounter
163
+ end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'active_record'
4
2
  require 'carrierwave/validations/active_model'
5
3
 
@@ -14,6 +12,35 @@ module CarrierWave
14
12
  def mount_uploader(column, uploader=nil, options={}, &block)
15
13
  super
16
14
 
15
+ class_eval <<-RUBY, __FILE__, __LINE__+1
16
+ def remote_#{column}_url=(url)
17
+ column = _mounter(:#{column}).serialization_column
18
+ send(:"\#{column}_will_change!")
19
+ super
20
+ end
21
+ RUBY
22
+ end
23
+
24
+ ##
25
+ # See +CarrierWave::Mount#mount_uploaders+ for documentation
26
+ #
27
+ def mount_uploaders(column, uploader=nil, options={}, &block)
28
+ super
29
+
30
+ class_eval <<-RUBY, __FILE__, __LINE__+1
31
+ def remote_#{column}_urls=(url)
32
+ column = _mounter(:#{column}).serialization_column
33
+ send(:"\#{column}_will_change!")
34
+ super
35
+ end
36
+ RUBY
37
+ end
38
+
39
+ private
40
+
41
+ def mount_base(column, uploader=nil, options={}, &block)
42
+ super
43
+
17
44
  alias_method :read_uploader, :read_attribute
18
45
  alias_method :write_uploader, :write_attribute
19
46
  public :read_uploader
@@ -29,43 +56,45 @@ module CarrierWave
29
56
  before_save :"write_#{column}_identifier"
30
57
  after_commit :"remove_#{column}!", :on => :destroy
31
58
  after_commit :"mark_remove_#{column}_false", :on => :update
32
- before_update :"store_previous_model_for_#{column}"
33
- after_save :"remove_previously_stored_#{column}"
59
+
60
+ after_save :"store_previous_changes_for_#{column}"
61
+ after_commit :"remove_previously_stored_#{column}", :on => :update
34
62
 
35
63
  class_eval <<-RUBY, __FILE__, __LINE__+1
36
64
  def #{column}=(new_file)
37
65
  column = _mounter(:#{column}).serialization_column
38
- send(:"\#{column}_will_change!")
66
+ if !(new_file.blank? && send(:#{column}).blank?)
67
+ send(:"\#{column}_will_change!")
68
+ end
69
+
39
70
  super
40
71
  end
41
72
 
42
- def remote_#{column}_url=(url)
73
+ def remove_#{column}=(value)
43
74
  column = _mounter(:#{column}).serialization_column
44
75
  send(:"\#{column}_will_change!")
45
76
  super
46
77
  end
47
78
 
48
79
  def remove_#{column}!
80
+ self.remove_#{column} = true
81
+ write_#{column}_identifier
82
+ self.remove_#{column} = false
49
83
  super
50
- _mounter(:#{column}).remove = true
51
- _mounter(:#{column}).write_identifier
52
84
  end
53
85
 
54
- def serializable_hash(options=nil)
55
- hash = {}
56
-
57
- except = options && options[:except] && Array.wrap(options[:except]).map(&:to_s)
58
- only = options && options[:only] && Array.wrap(options[:only]).map(&:to_s)
86
+ # Reset cached mounter on record reload
87
+ def reload(*)
88
+ @_mounters = nil
89
+ super
90
+ end
59
91
 
60
- self.class.uploaders.each do |column, uploader|
61
- if (!only && !except) || (only && only.include?(column.to_s)) || (!only && except && !except.include?(column.to_s))
62
- hash[column.to_s] = _mounter(column).uploader.serializable_hash
63
- end
64
- end
65
- super(options).merge(hash)
92
+ # Reset cached mounter on record dup
93
+ def initialize_dup(other)
94
+ @_mounters = nil
95
+ super
66
96
  end
67
97
  RUBY
68
-
69
98
  end
70
99
 
71
100
  end # ActiveRecord
@@ -1,3 +1,2 @@
1
1
  require "carrierwave/processing/rmagick"
2
2
  require "carrierwave/processing/mini_magick"
3
- require "carrierwave/processing/mime_types"
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
 
5
3
  ##
@@ -39,6 +37,7 @@ module CarrierWave
39
37
  # img
40
38
  # end
41
39
  # end
40
+ # end
42
41
  #
43
42
  # === Note
44
43
  #
@@ -49,7 +48,7 @@ module CarrierWave
49
48
  #
50
49
  # http://mini_magick.rubyforge.org/
51
50
  # and
52
- # https://github.com/minimagic/minimagick/
51
+ # https://github.com/minimagick/minimagick/
53
52
  #
54
53
  #
55
54
  module MiniMagick
@@ -81,7 +80,7 @@ module CarrierWave
81
80
  process :resize_to_fill => [width, height, gravity]
82
81
  end
83
82
 
84
- def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
83
+ def resize_and_pad(width, height, background=:transparent, gravity='Center')
85
84
  process :resize_and_pad => [width, height, background, gravity]
86
85
  end
87
86
  end
@@ -103,10 +102,10 @@ module CarrierWave
103
102
  #
104
103
  # image.convert(:png)
105
104
  #
106
- def convert(format)
105
+ def convert(format, page=nil)
107
106
  @format = format
107
+ @page = page
108
108
  manipulate! do |img|
109
- img.format(format.to_s.downcase)
110
109
  img = yield(img) if block_given?
111
110
  img
112
111
  end
@@ -127,9 +126,12 @@ module CarrierWave
127
126
  #
128
127
  # [MiniMagick::Image] additional manipulations to perform
129
128
  #
130
- def resize_to_limit(width, height)
129
+ def resize_to_limit(width, height, combine_options: {})
131
130
  manipulate! do |img|
132
- img.resize "#{width}x#{height}>"
131
+ img.combine_options do |cmd|
132
+ cmd.resize "#{width}x#{height}>"
133
+ append_combine_options cmd, combine_options
134
+ end
133
135
  img = yield(img) if block_given?
134
136
  img
135
137
  end
@@ -149,9 +151,12 @@ module CarrierWave
149
151
  #
150
152
  # [MiniMagick::Image] additional manipulations to perform
151
153
  #
152
- def resize_to_fit(width, height)
154
+ def resize_to_fit(width, height, combine_options: {})
153
155
  manipulate! do |img|
154
- img.resize "#{width}x#{height}"
156
+ img.combine_options do |cmd|
157
+ cmd.resize "#{width}x#{height}"
158
+ append_combine_options cmd, combine_options
159
+ end
155
160
  img = yield(img) if block_given?
156
161
  img
157
162
  end
@@ -172,7 +177,7 @@ module CarrierWave
172
177
  #
173
178
  # [MiniMagick::Image] additional manipulations to perform
174
179
  #
175
- def resize_to_fill(width, height, gravity = 'Center')
180
+ def resize_to_fill(width, height, gravity = 'Center', combine_options: {})
176
181
  manipulate! do |img|
177
182
  cols, rows = img[:dimensions]
178
183
  img.combine_options do |cmd|
@@ -192,6 +197,7 @@ module CarrierWave
192
197
  cmd.gravity gravity
193
198
  cmd.background "rgba(255,255,255,0.0)"
194
199
  cmd.extent "#{width}x#{height}" if cols != width || rows != height
200
+ append_combine_options cmd, combine_options
195
201
  end
196
202
  img = yield(img) if block_given?
197
203
  img
@@ -218,7 +224,7 @@ module CarrierWave
218
224
  #
219
225
  # [MiniMagick::Image] additional manipulations to perform
220
226
  #
221
- def resize_and_pad(width, height, background=:transparent, gravity='Center')
227
+ def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {})
222
228
  manipulate! do |img|
223
229
  img.combine_options do |cmd|
224
230
  cmd.thumbnail "#{width}x#{height}>"
@@ -229,12 +235,35 @@ module CarrierWave
229
235
  end
230
236
  cmd.gravity gravity
231
237
  cmd.extent "#{width}x#{height}"
238
+ append_combine_options cmd, combine_options
232
239
  end
233
240
  img = yield(img) if block_given?
234
241
  img
235
242
  end
236
243
  end
237
244
 
245
+ ##
246
+ # Returns the width of the image in pixels.
247
+ #
248
+ # === Returns
249
+ #
250
+ # [Integer] the image's width in pixels
251
+ #
252
+ def width
253
+ mini_magick_image[:width]
254
+ end
255
+
256
+ ##
257
+ # Returns the height of the image in pixels.
258
+ #
259
+ # === Returns
260
+ #
261
+ # [Integer] the image's height in pixels
262
+ #
263
+ def height
264
+ mini_magick_image[:height]
265
+ end
266
+
238
267
  ##
239
268
  # Manipulate the image with MiniMagick. This method will load up an image
240
269
  # and then pass each of its frames to the supplied block. It will then
@@ -260,9 +289,15 @@ module CarrierWave
260
289
  image = ::MiniMagick::Image.open(current_path)
261
290
 
262
291
  begin
263
- image.format(@format.to_s.downcase) if @format
292
+ image.format(@format.to_s.downcase, @page) if @format
264
293
  image = yield(image)
265
294
  image.write(current_path)
295
+
296
+ if @format
297
+ move_to = current_path.chomp(File.extname(current_path)) + ".#{@format}"
298
+ file.move_to(move_to, permissions, directory_permissions)
299
+ end
300
+
266
301
  image.run_command("identify", current_path)
267
302
  ensure
268
303
  image.destroy!
@@ -273,5 +308,21 @@ module CarrierWave
273
308
  raise CarrierWave::ProcessingError, message
274
309
  end
275
310
 
311
+ private
312
+
313
+ def append_combine_options(cmd, combine_options)
314
+ combine_options.each do |method, options|
315
+ cmd.send(method, options)
316
+ end
317
+ end
318
+
319
+ def mini_magick_image
320
+ if url
321
+ ::MiniMagick::Image.open(url)
322
+ else
323
+ ::MiniMagick::Image.open(current_path)
324
+ end
325
+ end
326
+
276
327
  end # MiniMagick
277
328
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
 
5
3
  ##
@@ -251,6 +249,28 @@ module CarrierWave
251
249
  end
252
250
  end
253
251
 
252
+ ##
253
+ # Returns the width of the image.
254
+ #
255
+ # === Returns
256
+ #
257
+ # [Integer] the image's width in pixels
258
+ #
259
+ def width
260
+ rmagick_image.columns
261
+ end
262
+
263
+ ##
264
+ # Returns the height of the image.
265
+ #
266
+ # === Returns
267
+ #
268
+ # [Integer] the image's height in pixels
269
+ #
270
+ def height
271
+ rmagick_image.rows
272
+ end
273
+
254
274
  ##
255
275
  # Manipulate the image with RMagick. This method will load up an image
256
276
  # and then pass each of its frames to the supplied block. It will then
@@ -324,11 +344,15 @@ module CarrierWave
324
344
  frames.append(true) if block_given?
325
345
 
326
346
  write_block = create_info_block(options[:write])
347
+
327
348
  if options[:format] || @format
328
349
  frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
350
+ move_to = current_path.chomp(File.extname(current_path)) + ".#{options[:format] || @format}"
351
+ file.move_to(move_to, permissions, directory_permissions)
329
352
  else
330
353
  frames.write(current_path, &write_block)
331
354
  end
355
+
332
356
  destroy_image(frames)
333
357
  rescue ::Magick::ImageMagickError => e
334
358
  raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e, :default => I18n.translate(:"errors.messages.rmagick_processing_error", :e => e, :locale => :en))
@@ -344,7 +368,11 @@ module CarrierWave
344
368
  end
345
369
 
346
370
  def destroy_image(image)
347
- image.destroy! if image.respond_to?(:destroy!)
371
+ image.try(:destroy!)
372
+ end
373
+
374
+ def rmagick_image
375
+ ::Magick::Image.read(current_path).first
348
376
  end
349
377
 
350
378
  end # RMagick