carrierwave 0.5.1 → 0.5.4

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
@@ -1,22 +1,20 @@
1
1
  = CarrierWave
2
2
 
3
- http://carrierwave.rubyforge.org
4
-
5
- == Summary
6
-
7
3
  This gem provides a simple and extremely flexible way to upload files from Ruby applications.
8
4
  It works well with Rack based web applications, such as Ruby on Rails.
9
5
 
10
- == Description
6
+ == Information
11
7
 
12
- * RDoc Documentation {available at Rubyforge}[http://carrierwave.rubyforge.org/rdoc].
13
- * Source code {hosted at GitHub}[http://github.com/jnicklas/carrierwave]
14
- * Please {report any issues}[http://github.com/jnicklas/carrierwave/issues] on GitHub
15
- * Please direct any questions at the {mailing list}[http://groups.google.com/group/carrierwave]
16
- * Check out the {example app}[http://github.com/jnicklas/carrierwave-example-app]
17
- * Instructions for setting up a development environment are at the bottom of this file
8
+ * RDoc documentation {available on RubyDoc.info}[http://rubydoc.info/gems/carrierwave/frames]
9
+ * Source code {available on GitHub}[http://github.com/jnicklas/carrierwave]
10
+ * More information, known limitations, and how-tos {available on the wiki}[https://github.com/jnicklas/carrierwave/wiki]
18
11
 
19
- == Getting Started
12
+ == Getting Help
13
+
14
+ * Please ask the {Groogle Group}[http://groups.google.com/group/carrierwave] for help if you have any questions.
15
+ * Please report bugs on the {issue tracker}[http://github.com/jnicklas/carrierwave/issues] but read the "getting help" section in the wiki first.
16
+
17
+ == Installation
20
18
 
21
19
  Install the latest stable release:
22
20
 
@@ -26,12 +24,10 @@ In Rails, add it to your Gemfile:
26
24
 
27
25
  gem 'carrierwave'
28
26
 
29
- CarrierWave is only compatible with Rails 3 and later as of version 0.5. If you want to use
30
- Rails 2, please use the latest gem in the 0.4.X series. You may also consider trying
31
- {this plugin}[http://github.com/gbuesing/carrierwave_rails23_compat] which allows CarrierWave
32
- to be used with a Rails 2.3 app.
27
+ Note that CarrierWave is not compatible with Rails 2 as of version 0.5. If you want to use
28
+ Rails 2, please use the 0.4-stable branch on GitHub.
33
29
 
34
- == Quick Start
30
+ == Getting Started
35
31
 
36
32
  Start off by generating an uploader:
37
33
 
@@ -94,6 +90,12 @@ automatically be stored when the record is saved.
94
90
  u.avatar.url # => '/url/to/file.png'
95
91
  u.avatar.current_path # => 'path/to/file.png'
96
92
 
93
+ If using DataMapper, make sure to disable auto_validation on the mounted column.
94
+
95
+ If using Mongoid, note that embedded documents files aren't saved when parent documents are saved.
96
+ You must explicitly call save on embedded documents in order to save their attached files.
97
+ You can read more about this {here}[https://github.com/jnicklas/carrierwave/issues#issue/81]
98
+
97
99
  == Changing the storage directory
98
100
 
99
101
  In order to change where uploaded files are put, just override the +store_dir+
@@ -123,6 +125,63 @@ make the record invalid instead. Otherwise, an error is raised.
123
125
  end
124
126
  end
125
127
 
128
+ === Validating Uploads
129
+
130
+ Standard active model validations can be used to ensure a file is uploaded.
131
+
132
+ mount_uploader :avatar, AvatarUploader
133
+
134
+ validate_presence_of :avatar
135
+
136
+ CarrierWave also supplies additional validations, such as validating the integrity of an uploaded file.
137
+
138
+ validates_integrity_of :avatar
139
+
140
+ or validating that the file was sucessfully processed
141
+
142
+ validates_processing_of :avatar
143
+
144
+ The validations use translated error messages and can be changed using i18n localization
145
+
146
+ en:
147
+ errors:
148
+ messages:
149
+ carrierwave_processing_error: failed to be processed
150
+ carrierwave_integrity_error: is not an allowed file type
151
+
152
+
153
+ === Filenames and unicode chars
154
+
155
+ Another security issue you should care for is the file names (see
156
+ {Ruby On Rails Security Guide}[http://guides.rubyonrails.org/security.html#file-uploads]).
157
+ By default, CarrierWave provides only English letters, arabic numerals and '-+_.' symbols as
158
+ white-listed characters in the file name.
159
+
160
+ If you want to support local scripts (Cyrillic letters, letters with diacritics and so on), you
161
+ have to override +sanitize_regexp+ method. It should return regular expression which would match
162
+ all *non*-allowed symbols.
163
+
164
+ With Ruby 1.9 and higher you can simply write (as it has {Oniguruma}[http://oniguruma.rubyforge.org/oniguruma/]
165
+ built-in):
166
+
167
+ class MyUploader < CarrierWave::Uploader::Base
168
+ def sanitize_regexp
169
+ /[^[:word:]\.\-\+]/
170
+ end
171
+ end
172
+
173
+ With Ruby 1.8.* you have to manually specify all character ranges. For example, for files which may
174
+ contain Russian letters:
175
+
176
+ class MyUploader < CarrierWave::Uploader::Base
177
+ def sanitize_regexp
178
+ /[^a-zA-Zа-яА-ЯёЁ0-9\.\-\+_]/u
179
+ end
180
+ end
181
+
182
+ Also make sure that allowing non-latin characters won't cause a compatibility issue with a third-party
183
+ plugins or client-side software.
184
+
126
185
  == Adding versions
127
186
 
128
187
  Often you'll want to add different versions of the same file. The classic
@@ -243,7 +302,7 @@ this easily by overriding the +default_url+ method in your uploader:
243
302
 
244
303
  You might come to a situation where you want to retroactively change a version
245
304
  or add a new one. You can use the recreate_versions! method to recreate the
246
- versions from the base file. This uses a naive approach which will reupload and
305
+ versions from the base file. This uses a naive approach which will re-upload and
247
306
  process all versions.
248
307
 
249
308
  instance = MyUploader.new
@@ -275,7 +334,7 @@ If you're using Rails, create an initializer for this:
275
334
 
276
335
  config/initializers/carrierwave.rb
277
336
 
278
- == Testing CarrierWave
337
+ == Testing with CarrierWave
279
338
 
280
339
  It's a good idea to test you uploaders in isolation. In order to speed up your
281
340
  tests, it's recommended to switch off processing in your tests, and to use the
@@ -331,48 +390,90 @@ Fog[http://github.com/geemus/fog] is used to support Amazon S3. Ensure you have
331
390
 
332
391
  gem install fog
333
392
 
334
- You'll need to configure a bucket, access id and secret key like this in an initializer:
393
+ You'll need to provide your fog_credentials and a fog_directory (also known as a bucket) in an initializer.
394
+ For the sake of performance it is assumed that the directory already exists, so please create it if need be.
395
+ You can also pass in additional options, as documented fully in lib/carrierwave/storage/fog.rb. Here's a full example:
335
396
 
336
397
  CarrierWave.configure do |config|
337
- config.s3_access_key_id = 'xxxxxx'
338
- config.s3_secret_access_key = 'xxxxxx'
339
- config.s3_bucket = 'name_of_bucket'
398
+ config.fog_credentials = {
399
+ :provider => 'AWS', # required
400
+ :aws_access_key_id => 'xxx', # required
401
+ :aws_secret_access_key => 'yyy', # required
402
+ :region => 'eu-west-1' # optional, defaults to 'us-east-1'
403
+ }
404
+ config.fog_directory = 'name_of_directory' # required
405
+ config.fog_host = 'https://assets.example.com' # optional, defaults to nil
406
+ config.fog_public = false # optional, defaults to true
407
+ config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
340
408
  end
341
409
 
342
- In your uploader, set the storage to :s3
410
+ In your uploader, set the storage to :fog
343
411
 
344
412
  class AvatarUploader < CarrierWave::Uploader::Base
345
- storage :s3
413
+ storage :fog
346
414
  end
347
415
 
348
- That's it! You can still use the <code>CarrierWave::Uploader#url</code> method to return
349
- the url to the file on Amazon S3.
416
+ That's it! You can still use the <code>CarrierWave::Uploader#url</code> method to return the url to the file on Amazon S3.
350
417
 
351
418
  == Using Rackspace Cloud Files
352
419
 
353
- Cloud Files support requires a {Rackspace Cloud}[http://rackspacecloud.com] username and API key.
354
- You must also create a container for Carrierwave to use, and mark it public (publish it to the CDN)
420
+ Fog[http://github.com/geemus/fog] is used to support Rackspace Cloud Files. Ensure you have it installed:
421
+
422
+ gem install fog
423
+
424
+ You'll need to configure a directory (also known as a container), username and api key in the initializer.
425
+ For the sake of performance it is assumed that the directory already exists, so please create it if need be.
355
426
 
356
427
  CarrierWave.configure do |config|
357
- config.cloud_files_username = 'xxxxxx'
358
- config.cloud_files_api_key = 'xxxxxxxxxxxxxxxxxxxxx'
359
- config.cloud_files_container = 'name_of_bucket'
428
+ config.fog_credentials = {
429
+ :provider => 'Rackspace',
430
+ :rackspace_username => 'xxxxxx',
431
+ :rackspace_api_key => 'yyyyyy'
432
+ }
433
+ config.fog_directory = 'name_of_directory'
360
434
  end
361
435
 
362
436
  You can optionally include your CDN host name in the configuration.
363
437
  This is *highly* recommended, as without it every request requires a lookup
364
438
  of this information.
365
439
 
366
- config.cloud_files_cdn_host = "c000000.cdn.rackspacecloud.com"
440
+ config.fog_host = "c000000.cdn.rackspacecloud.com"
367
441
 
368
- In your uploader, set the storage to :cloud_files
442
+ In your uploader, set the storage to :fog
369
443
 
370
444
  class AvatarUploader < CarrierWave::Uploader::Base
371
- storage :cloud_files
445
+ storage :fog
372
446
  end
373
447
 
374
448
  That's it! You can still use the <code>CarrierWave::Uploader#url</code> method to return
375
- the url to the file on the Cloud Files CDN.
449
+ the url to the file on Rackspace Cloud Files.
450
+
451
+ == Using Google Storage for Developers
452
+
453
+ Fog[http://github.com/geemus/fog] is used to support Google Storage for Developers. Ensure you have it installed:
454
+
455
+ gem install fog
456
+
457
+ You'll need to configure a directory (also known as a bucket), access key id and secret access key in the initialiazer.
458
+ For the sake of performance it is assumed that the directory already exists, so please create it if need be.
459
+
460
+ CarrierWave.configure do |config|
461
+ config.fog_credentials = {
462
+ :provider => 'Google',
463
+ :google_storage_access_key_id => 'xxxxxx',
464
+ :google_storage_secret_access_key => 'yyyyyy'
465
+ }
466
+ config.fog_directory = 'name_of_directory'
467
+ end
468
+
469
+ In your uploader, set the storage to :fog
470
+
471
+ class AvatarUploader < CarrierWave::Uploader::Base
472
+ storage :fog
473
+ end
474
+
475
+ That's it! You can still use the <code>CarrierWave::Uploader#url</code> method to return
476
+ the url to the file on Google.
376
477
 
377
478
  == Using MongoDB's GridFS store
378
479
 
@@ -463,7 +564,7 @@ for the RMagick processor.
463
564
  process :resize_to_fill => [200, 200]
464
565
  end
465
566
 
466
- == Migrating
567
+ == Migrating from Paperclip
467
568
 
468
569
  If you are using Paperclip, you can use the provided compatibility module:
469
570
 
@@ -472,19 +573,19 @@ If you are using Paperclip, you can use the provided compatibility module:
472
573
  end
473
574
 
474
575
  See the documentation for <code>CarrierWave::Compatibility::Paperclip</code> for more
475
- detaills.
576
+ details.
476
577
 
477
578
  Be sure to use mount_on to specify the correct column:
478
579
 
479
580
  mount_uploader :avatar, AvatarUploader, :mount_on => :avatar_file_name
480
581
 
481
- Unfortunately AttachmentFoo differs too much in philosophy for there to be a
582
+ Unfortunately attachment_fu differs too much in philosophy for there to be a
482
583
  sensible compatibility mode. Patches for migrating from other solutions will be
483
584
  happily accepted.
484
585
 
485
586
  == i18n
486
587
 
487
- The activerecord validations use the Rails i18n framework. Add these keys to
588
+ The Active Record validations use the Rails i18n framework. Add these keys to
488
589
  your translations file:
489
590
 
490
591
  errors:
@@ -492,6 +593,36 @@ your translations file:
492
593
  carrierwave_processing_error: 'Cannot resize image.'
493
594
  carrierwave_integrity_error: 'Not an image.'
494
595
 
596
+ == Contributing to CarrierWave
597
+
598
+ CarrierWave thrives on a large number of {contributors}[https://github.com/jnicklas/carrierwave/contributors],
599
+ and pull requests are very welcome. Before submitting a pull request, please make sure that your changes are well tested.
600
+
601
+ You'll need to install bundler and the gem dependencies:
602
+
603
+ gem install bundler
604
+ bundle install
605
+
606
+ You should now be able to run the local tests:
607
+
608
+ bundle exec rake
609
+
610
+ You can also run the remote specs by creating a ~/.fog file:
611
+
612
+ :carrierwave:
613
+ :aws_access_key_id: xxx
614
+ :aws_secret_access_key: yyy
615
+ :rackspace_username: xxx
616
+ :rackspace_api_key: yyy
617
+ :google_storage_access_key_id: xxx
618
+ :google_storage_secret_access_key: yyy
619
+
620
+ You should now be able to run the remote tests:
621
+
622
+ REMOTE=true bundle exec rake
623
+
624
+ Please test with the latest Ruby 1.8.x and 1.9.x versions using RVM if possible.
625
+
495
626
  == License
496
627
 
497
628
  Copyright (c) 2008 Jonas Nicklas
@@ -514,21 +645,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
514
645
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
515
646
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
516
647
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
517
-
518
- == Development
519
-
520
- In order to setup a development environment and run the specs, you'll
521
- need to install bundler:
522
-
523
- gem install bundler
524
-
525
- And then install the dependencies:
526
-
527
- bundle install
528
-
529
- You should now be able to run the tests:
530
-
531
- bundle exec rake
532
-
533
- Issues are reported on GitHub, pull requests are very welcome!
534
-
@@ -11,7 +11,7 @@ module CarrierWave
11
11
  #
12
12
  # class MyUploader < CarrierWave::Uploader::Base
13
13
  # include CarrierWave::Compatibility::Paperclip
14
- #
14
+ #
15
15
  # def paperclip_path
16
16
  # ":rails_root/public/uploads/:id/:attachment/:style_:basename.:extension"
17
17
  # end
@@ -20,23 +20,23 @@ module CarrierWave
20
20
  # ---
21
21
  #
22
22
  # This file contains code taken from Paperclip
23
- #
23
+ #
24
24
  # LICENSE
25
- #
25
+ #
26
26
  # The MIT License
27
- #
27
+ #
28
28
  # Copyright (c) 2008 Jon Yurek and thoughtbot, inc.
29
- #
29
+ #
30
30
  # Permission is hereby granted, free of charge, to any person obtaining a copy
31
31
  # of this software and associated documentation files (the "Software"), to deal
32
32
  # in the Software without restriction, including without limitation the rights
33
33
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34
34
  # copies of the Software, and to permit persons to whom the Software is
35
35
  # furnished to do so, subject to the following conditions:
36
- #
36
+ #
37
37
  # The above copyright notice and this permission notice shall be included in
38
38
  # all copies or substantial portions of the Software.
39
- #
39
+ #
40
40
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41
41
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42
42
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -77,17 +77,17 @@ module CarrierWave
77
77
  end
78
78
 
79
79
  def mappings
80
- {
81
- :rails_root => lambda{|u, f| Rails.root },
82
- :rails_env => lambda{|u, f| Rails.env },
83
- :class => lambda{|u, f| u.model.class.name.underscore.pluralize},
84
- :id => lambda{|u, f| u.model.id },
85
- :id_partition => lambda{|u, f| ("%09d" % u.model.id).scan(/\d{3}/).join("/")},
86
- :attachment => lambda{|u, f| u.mounted_as.to_s.downcase.pluralize },
87
- :style => lambda{|u, f| u.paperclip_style },
88
- :basename => lambda{|u, f| f.gsub(/#{File.extname(f)}$/, "") },
89
- :extension => lambda{|u, f| File.extname(f).gsub(/^\.+/, "")}
90
- }
80
+ [
81
+ [:rails_root , lambda{|u, f| Rails.root }],
82
+ [:rails_env , lambda{|u, f| Rails.env }],
83
+ [:class , lambda{|u, f| u.model.class.name.underscore.pluralize}],
84
+ [:id_partition , lambda{|u, f| ("%09d" % u.model.id).scan(/\d{3}/).join("/")}],
85
+ [:id , lambda{|u, f| u.model.id }],
86
+ [:attachment , lambda{|u, f| u.mounted_as.to_s.downcase.pluralize }],
87
+ [:style , lambda{|u, f| u.paperclip_style }],
88
+ [:basename , lambda{|u, f| f.gsub(/#{File.extname(f)}$/, "") }],
89
+ [:extension , lambda{|u, f| File.extname(f).gsub(/^\.+/, "")}]
90
+ ]
91
91
  end
92
92
 
93
93
  end # Paperclip
@@ -80,7 +80,7 @@ module CarrierWave
80
80
  #
81
81
  # [image_url] Returns the url to the uploaded file
82
82
  #
83
- # [image_cache] Returns a string that identifies the cache location of the file
83
+ # [image_cache] Returns a string that identifies the cache location of the file
84
84
  # [image_cache=] Retrieves the file from the cache based on the given cache name
85
85
  #
86
86
  # [remote_image_url] Returns previously cached remote url
@@ -106,7 +106,7 @@ module CarrierWave
106
106
  # [&block (Proc)] customize anonymous uploaders
107
107
  #
108
108
  # === Options
109
- #
109
+ #
110
110
  # [:mount_on => Symbol] if the name of the column to be serialized to differs you can override it using this option
111
111
  # [:ignore_integrity_errors => Boolean] if set to true, integrity errors will result in caching failing silently
112
112
  # [:ignore_processing_errors => Boolean] if set to true, processing errors will result in caching failing silently
@@ -256,6 +256,7 @@ module CarrierWave
256
256
  # this is an internal class, used by CarrierWave::Mount so that
257
257
  # we don't pollute the model with a lot of methods.
258
258
  class Mounter #:nodoc:
259
+ extend ActiveSupport::Memoizable
259
260
 
260
261
  attr_reader :column, :record, :remote_url, :integrity_error, :processing_error
261
262
  attr_accessor :remove
@@ -273,7 +274,7 @@ module CarrierWave
273
274
  record.write_uploader(serialization_column, uploader.identifier)
274
275
  end
275
276
  end
276
-
277
+
277
278
  def identifier
278
279
  record.read_uploader(serialization_column)
279
280
  end
@@ -311,7 +312,7 @@ module CarrierWave
311
312
  def remote_url=(url)
312
313
  unless uploader.cached?
313
314
  @remote_url = url
314
- uploader.download!(url)
315
+ uploader.download!(url)
315
316
  end
316
317
  end
317
318
 
@@ -342,10 +343,11 @@ module CarrierWave
342
343
  end
343
344
 
344
345
  private
345
-
346
+
346
347
  def option(name)
347
348
  record.class.uploader_option(column, name)
348
349
  end
350
+ memoize :option
349
351
 
350
352
  def serialization_column
351
353
  option(:mount_on) || column
@@ -24,9 +24,16 @@ module CarrierWave
24
24
  validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
25
25
  validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
26
26
 
27
- after_save "store_#{column}!"
28
- before_save "write_#{column}_identifier"
29
- after_destroy "remove_#{column}!"
27
+ after_save :"store_#{column}!"
28
+ before_save :"write_#{column}_identifier"
29
+ after_destroy :"remove_#{column}!"
30
+
31
+ class_eval <<-RUBY, __FILE__, __LINE__+1
32
+ def #{column}=(new_file)
33
+ #{column}_will_change!
34
+ super
35
+ end
36
+ RUBY
30
37
 
31
38
  end
32
39
 
@@ -24,7 +24,7 @@ module CarrierWave
24
24
  # for objects that are not dirty. By explicitly calling
25
25
  # attribute_set we are marking the record as dirty.
26
26
  class_eval <<-RUBY
27
- def remove_image=(value)
27
+ def remove_#{column}=(value)
28
28
  _mounter(:#{column}).remove = value
29
29
  attribute_set(:#{column}, '') if _mounter(:#{column}).remove?
30
30
  end
@@ -1,25 +1,25 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'sequel'
4
-
4
+
5
5
  module CarrierWave
6
6
  module Sequel
7
7
  include CarrierWave::Mount
8
-
8
+
9
9
  def mount_uploader(column, uploader)
10
10
  raise "You need to use Sequel 3.0 or higher. Please upgrade." unless ::Sequel::Model.respond_to?(:plugin)
11
11
  super
12
-
12
+
13
13
  alias_method :read_uploader, :[]
14
14
  alias_method :write_uploader, :[]=
15
-
15
+
16
16
  include CarrierWave::Sequel::Hooks
17
17
  include CarrierWave::Sequel::Validations
18
18
  end
19
19
 
20
20
  end # Sequel
21
21
  end # CarrierWave
22
-
22
+
23
23
  # Instance hook methods for the Sequel 3.x
24
24
  module CarrierWave::Sequel::Hooks
25
25
  def after_save
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "image_science"
3
+ require 'image_science'
4
4
 
5
5
  module CarrierWave
6
6
  module ImageScience
@@ -34,6 +34,8 @@ module CarrierWave
34
34
  # [height (Integer)] the height to scale the image to
35
35
  #
36
36
  def resize_to_fit(new_width, new_height)
37
+ cache_stored_file! if !cached?
38
+
37
39
  ::ImageScience.with_image(self.current_path) do |img|
38
40
  width, height = extract_dimensions(img.width, img.height, new_width, new_height)
39
41
  img.resize( width, height ) do |file|
@@ -55,19 +57,38 @@ module CarrierWave
55
57
  # [height (Integer)] the height to scale the image to
56
58
  #
57
59
  def resize_to_fill(new_width, new_height)
60
+ cache_stored_file! if !cached?
61
+
58
62
  ::ImageScience.with_image(self.current_path) do |img|
59
63
  width, height = extract_dimensions_for_crop(img.width, img.height, new_width, new_height)
60
64
  x_offset, y_offset = extract_placement_for_crop(width, height, new_width, new_height)
61
65
 
66
+ # check if if new dimensions are too small for the new image
67
+ if width < new_width
68
+ width = new_width
69
+ height = (new_width.to_f*(img.height.to_f/img.width.to_f)).round
70
+ elsif height < new_height
71
+ height = new_height
72
+ width = (new_height.to_f*(img.width.to_f/img.height.to_f)).round
73
+ end
74
+
62
75
  img.resize( width, height ) do |i2|
63
76
 
77
+ # check to make sure offset is not negative
78
+ if x_offset < 0
79
+ x_offset = 0
80
+ end
81
+ if y_offset < 0
82
+ y_offset = 0
83
+ end
84
+
64
85
  i2.with_crop( x_offset, y_offset, new_width + x_offset, new_height + y_offset) do |file|
65
86
  file.save( self.current_path )
66
87
  end
67
88
  end
68
89
  end
69
90
  end
70
-
91
+
71
92
  ##
72
93
  # Resize the image to fit within the specified dimensions while retaining
73
94
  # the original aspect ratio. Will only resize the image if it is larger than the
@@ -80,6 +101,8 @@ module CarrierWave
80
101
  # [height (Integer)] the height to scale the image to
81
102
  #
82
103
  def resize_to_limit(new_width, new_height)
104
+ cache_stored_file! if !cached?
105
+
83
106
  ::ImageScience.with_image(self.current_path) do |img|
84
107
  if img.width > new_width or img.height > new_height
85
108
  resize_to_fit(new_width, new_height)
@@ -249,6 +249,7 @@ module CarrierWave
249
249
  # [CarrierWave::ProcessingError] if manipulation failed.
250
250
  #
251
251
  def manipulate!
252
+ cache_stored_file! if !cached?
252
253
  image = ::MiniMagick::Image.open(current_path)
253
254
  image = yield(image)
254
255
  image.write(current_path)
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- unless defined? Magick
3
+ unless defined? Magick
4
4
  begin
5
5
  require 'rmagick'
6
6
  rescue LoadError
@@ -244,6 +244,7 @@ module CarrierWave
244
244
  # [CarrierWave::ProcessingError] if manipulation failed.
245
245
  #
246
246
  def manipulate!(options={})
247
+ cache_stored_file! if !cached?
247
248
  image = ::Magick::Image.read(current_path)
248
249
 
249
250
  frames = if image.size > 1
@@ -269,7 +270,7 @@ module CarrierWave
269
270
  end
270
271
 
271
272
  private
272
-
273
+
273
274
  def destroy_image(image)
274
275
  image.destroy! if image.respond_to?(:destroy!)
275
276
  end
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'pathname'
4
+ require 'active_support/core_ext/string/multibyte'
4
5
 
5
6
  module CarrierWave
6
7
 
@@ -147,7 +148,7 @@ module CarrierWave
147
148
  #
148
149
  def read
149
150
  if is_path?
150
- File.open(@file, "rb").read
151
+ File.open(@file, "rb") {|file| file.read}
151
152
  else
152
153
  @file.rewind if @file.respond_to?(:rewind)
153
154
  @file.read
@@ -221,6 +222,17 @@ module CarrierWave
221
222
  @file.content_type.chomp if @file.respond_to?(:content_type) and @file.content_type
222
223
  end
223
224
 
225
+ ##
226
+ # Used to sanitize the file name. Public to allow overriding for non-latin characters.
227
+ #
228
+ # === Returns
229
+ #
230
+ # [Regexp] the regexp for sanitizing the file name
231
+ #
232
+ def sanitize_regexp
233
+ /[^a-zA-Z0-9\.\-\+_]/
234
+ end
235
+
224
236
  private
225
237
 
226
238
  def file=(file)
@@ -248,10 +260,10 @@ module CarrierWave
248
260
  def sanitize(name)
249
261
  name = name.gsub("\\", "/") # work-around for IE
250
262
  name = File.basename(name)
251
- name = name.gsub(/[^a-zA-Z0-9\.\-\+_]/,"_")
263
+ name = name.gsub(sanitize_regexp,"_")
252
264
  name = "_#{name}" if name =~ /\A\.+\z/
253
265
  name = "unnamed" if name.size == 0
254
- return name.downcase
266
+ return name.mb_chars.downcase.to_s
255
267
  end
256
268
 
257
269
  def split_extension(filename)