carrierwave 0.1 → 0.2.0
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.
- data/LICENSE +1 -1
- data/{README.md → README.rdoc} +73 -78
- data/Rakefile +12 -6
- data/lib/carrierwave.rb +33 -17
- data/lib/carrierwave/mount.rb +133 -54
- data/lib/carrierwave/orm/activerecord.rb +53 -2
- data/lib/carrierwave/orm/datamapper.rb +7 -2
- data/lib/carrierwave/orm/sequel.rb +23 -0
- data/lib/carrierwave/processing/image_science.rb +3 -3
- data/lib/carrierwave/processing/rmagick.rb +103 -47
- data/lib/carrierwave/sanitized_file.rb +74 -48
- data/lib/carrierwave/storage/abstract.rb +24 -9
- data/lib/carrierwave/storage/file.rb +23 -9
- data/lib/carrierwave/storage/s3.rb +67 -16
- data/lib/carrierwave/test/matchers.rb +112 -0
- data/lib/carrierwave/uploader.rb +264 -113
- data/lib/generators/uploader_generator.rb +7 -7
- data/rails_generators/uploader/templates/uploader.rb +9 -1
- data/spec/mount_spec.rb +147 -3
- data/spec/orm/activerecord_spec.rb +24 -3
- data/spec/orm/datamapper_spec.rb +3 -3
- data/spec/orm/sequel_spec.rb +170 -0
- data/spec/sanitized_file_spec.rb +22 -36
- data/spec/spec_helper.rb +44 -80
- data/spec/uploader_spec.rb +107 -22
- metadata +8 -4
@@ -4,17 +4,68 @@ module CarrierWave
|
|
4
4
|
module ActiveRecord
|
5
5
|
|
6
6
|
include CarrierWave::Mount
|
7
|
+
|
8
|
+
##
|
9
|
+
# See +CarrierWave::Mount#mount_uploader+ for documentation
|
10
|
+
#
|
11
|
+
def mount_uploader(column, uploader, options={}, &block)
|
12
|
+
super
|
7
13
|
|
8
|
-
def after_mount(column, uploader)
|
9
14
|
alias_method :read_uploader, :read_attribute
|
10
15
|
alias_method :write_uploader, :write_attribute
|
11
16
|
|
17
|
+
validates_integrity_of column if uploader_options[column.to_sym][:validate_integrity]
|
18
|
+
validates_processing_of column if uploader_options[column.to_sym][:validate_processing]
|
19
|
+
|
12
20
|
before_save do |record|
|
13
21
|
record.send("store_#{column}!")
|
14
22
|
end
|
15
23
|
end
|
16
24
|
|
25
|
+
##
|
26
|
+
# Makes the record invalid if the file couldn't be uploaded due to an integrity error
|
27
|
+
#
|
28
|
+
# Accepts the usual parameters for validations in Rails (:if, :unless, etc...)
|
29
|
+
#
|
30
|
+
# === Note
|
31
|
+
#
|
32
|
+
# Set this key in your translations file for I18n:
|
33
|
+
#
|
34
|
+
# carrierwave:
|
35
|
+
# errors:
|
36
|
+
# integrity: 'Here be an error message'
|
37
|
+
#
|
38
|
+
def validates_integrity_of(*attrs)
|
39
|
+
options = attrs.last.is_a?(Hash) ? attrs.last : {}
|
40
|
+
options[:message] ||= I18n.t('carrierwave.errors.integrity', :default => 'is not an allowed type of file.')
|
41
|
+
validates_each(*attrs) do |record, attr, value|
|
42
|
+
record.errors.add attr, options[:message] if record.send("#{attr}_integrity_error")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Makes the record invalid if the file couldn't be processed (assuming the process failed
|
48
|
+
# with a CarrierWave::ProcessingError)
|
49
|
+
#
|
50
|
+
# Accepts the usual parameters for validations in Rails (:if, :unless, etc...)
|
51
|
+
#
|
52
|
+
# === Note
|
53
|
+
#
|
54
|
+
# Set this key in your translations file for I18n:
|
55
|
+
#
|
56
|
+
# carrierwave:
|
57
|
+
# errors:
|
58
|
+
# processing: 'Here be an error message'
|
59
|
+
#
|
60
|
+
def validates_processing_of(*attrs)
|
61
|
+
options = attrs.last.is_a?(Hash) ? attrs.last : {}
|
62
|
+
options[:message] ||= I18n.t('carrierwave.errors.processing', :default => 'failed to be processed.')
|
63
|
+
validates_each(*attrs) do |record, attr, value|
|
64
|
+
record.errors.add attr, options[:message] if record.send("#{attr}_processing_error")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
17
68
|
end # ActiveRecord
|
18
69
|
end # CarrierWave
|
19
70
|
|
20
|
-
ActiveRecord::Base.send(:extend, CarrierWave::ActiveRecord)
|
71
|
+
ActiveRecord::Base.send(:extend, CarrierWave::ActiveRecord)
|
@@ -5,7 +5,12 @@ module CarrierWave
|
|
5
5
|
|
6
6
|
include CarrierWave::Mount
|
7
7
|
|
8
|
-
|
8
|
+
##
|
9
|
+
# See +CarrierWave::Mount#mount_uploader+ for documentation
|
10
|
+
#
|
11
|
+
def mount_uploader(column, uploader, options={}, &block)
|
12
|
+
super
|
13
|
+
|
9
14
|
alias_method :read_uploader, :attribute_get
|
10
15
|
alias_method :write_uploader, :attribute_set
|
11
16
|
|
@@ -17,4 +22,4 @@ module CarrierWave
|
|
17
22
|
end # DataMapper
|
18
23
|
end # CarrierWave
|
19
24
|
|
20
|
-
DataMapper::Model.send(:include, CarrierWave::DataMapper)
|
25
|
+
DataMapper::Model.send(:include, CarrierWave::DataMapper)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Sequel
|
5
|
+
|
6
|
+
include CarrierWave::Mount
|
7
|
+
|
8
|
+
def mount_uploader(column, uploader)
|
9
|
+
super
|
10
|
+
|
11
|
+
alias_method :read_uploader, :[]
|
12
|
+
alias_method :write_uploader, :[]=
|
13
|
+
|
14
|
+
before_save do
|
15
|
+
send("store_#{column}!")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end # Sequel
|
20
|
+
end # CarrierWave
|
21
|
+
|
22
|
+
Sequel::Model.send(:extend, CarrierWave::Sequel)
|
23
|
+
|
@@ -2,7 +2,7 @@ require "image_science"
|
|
2
2
|
|
3
3
|
module CarrierWave
|
4
4
|
module ImageScience
|
5
|
-
|
5
|
+
|
6
6
|
# Resize the image so that it will not exceed the dimensions passed
|
7
7
|
# via geometry, geometry should be a string, formatted like '200x100' where
|
8
8
|
# the first number is the height and the second is the width
|
@@ -63,8 +63,8 @@ module CarrierWave
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def convert_geometry(geometry)
|
66
|
-
geometry.split('x').map{|i| i.to_f }
|
66
|
+
geometry.split('x').map{|i| i.to_f }
|
67
67
|
end
|
68
68
|
|
69
69
|
end # ImageScience
|
70
|
-
end # CarrierWave
|
70
|
+
end # CarrierWave
|
@@ -1,37 +1,40 @@
|
|
1
1
|
require 'rmagick'
|
2
2
|
|
3
3
|
module CarrierWave
|
4
|
-
|
4
|
+
|
5
5
|
##
|
6
6
|
# This module simplifies manipulation with RMagick by providing a set
|
7
7
|
# of convenient helper methods. If you want to use them, you'll need to
|
8
|
-
# require this file
|
8
|
+
# require this file:
|
9
9
|
#
|
10
10
|
# require 'carrierwave/processing/rmagick'
|
11
11
|
#
|
12
|
-
# And then include it in your uploader
|
12
|
+
# And then include it in your uploader:
|
13
13
|
#
|
14
|
-
#
|
14
|
+
# class MyUploader
|
15
|
+
# include CarrierWave::Uploader
|
15
16
|
# include CarrierWave::RMagick
|
16
17
|
# end
|
17
18
|
#
|
18
19
|
# You can now use the provided helpers:
|
19
20
|
#
|
20
|
-
#
|
21
|
+
# class MyUploader
|
22
|
+
# include CarrierWave::Uploader
|
21
23
|
# include CarrierWave::RMagick
|
22
|
-
#
|
23
|
-
# process :resize_to_fit => [200, 200]
|
24
|
+
#
|
25
|
+
# process :resize_to_fit => [200, 200]
|
24
26
|
# end
|
25
27
|
#
|
26
28
|
# Or create your own helpers with the powerful manipulate! method. Check
|
27
29
|
# out the RMagick docs at http://www.imagemagick.org/RMagick/doc/ for more
|
28
30
|
# info
|
29
31
|
#
|
30
|
-
#
|
32
|
+
# class MyUploader
|
33
|
+
# include CarrierWave::Uploader
|
31
34
|
# include CarrierWave::RMagick
|
32
|
-
#
|
35
|
+
#
|
33
36
|
# process :do_stuff => 10.0
|
34
|
-
#
|
37
|
+
#
|
35
38
|
# def do_stuff(blur_factor)
|
36
39
|
# manipulate! do |img|
|
37
40
|
# img = img.sepiatone
|
@@ -41,17 +44,41 @@ module CarrierWave
|
|
41
44
|
# end
|
42
45
|
# end
|
43
46
|
#
|
47
|
+
# === Note
|
48
|
+
#
|
49
|
+
# You should be aware how RMagick handles memory. manipulate! takes care
|
50
|
+
# of freeing up memory for you, but for optimum memory usage you should
|
51
|
+
# use destructive operations as much as possible:
|
52
|
+
#
|
53
|
+
# DON'T DO THIS:
|
54
|
+
# img = img.resize_to_fit
|
55
|
+
#
|
56
|
+
# DO THIS INSTEAD:
|
57
|
+
# img.resize_to_fit!
|
58
|
+
#
|
59
|
+
# Read this for more information why:
|
60
|
+
#
|
61
|
+
# http://rubyforge.org/forum/forum.php?thread_id=1374&forum_id=1618
|
62
|
+
#
|
44
63
|
module RMagick
|
45
|
-
|
64
|
+
|
46
65
|
##
|
47
66
|
# Changes the image encoding format to the given format
|
48
67
|
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
68
|
+
# See even http://www.imagemagick.org/RMagick/doc/magick.html#formats
|
69
|
+
#
|
70
|
+
# === Parameters
|
71
|
+
#
|
72
|
+
# [format (#to_s)] an abreviation of the format
|
73
|
+
#
|
74
|
+
# === Yields
|
75
|
+
#
|
76
|
+
# [Magick::Image] additional manipulations to perform
|
77
|
+
#
|
78
|
+
# === Examples
|
79
|
+
#
|
53
80
|
# image.convert(:png)
|
54
|
-
#
|
81
|
+
#
|
55
82
|
def convert(format)
|
56
83
|
manipulate! do |img|
|
57
84
|
img.format = format.to_s.upcase
|
@@ -66,12 +93,17 @@ module CarrierWave
|
|
66
93
|
# image may be shorter or narrower than specified in the smaller dimension
|
67
94
|
# but will not be larger than the specified values."
|
68
95
|
#
|
69
|
-
#
|
96
|
+
# See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
|
97
|
+
#
|
98
|
+
# === Parameters
|
99
|
+
#
|
100
|
+
# [width (Integer)] the width to scale the image to
|
101
|
+
# [height (Integer)] the height to scale the image to
|
102
|
+
#
|
103
|
+
# === Yields
|
104
|
+
#
|
105
|
+
# [Magick::Image] additional manipulations to perform
|
70
106
|
#
|
71
|
-
# @param [Integer] width the width to scale the image to
|
72
|
-
# @param [Integer] height the height to scale the image to
|
73
|
-
# @yieldparam [Magick::Image] img additional manipulations to perform
|
74
|
-
#
|
75
107
|
def resize_to_fit(width, height)
|
76
108
|
manipulate! do |img|
|
77
109
|
img.resize_to_fit!(width, height)
|
@@ -79,7 +111,7 @@ module CarrierWave
|
|
79
111
|
img
|
80
112
|
end
|
81
113
|
end
|
82
|
-
|
114
|
+
|
83
115
|
alias_method :resize, :resize_to_fit
|
84
116
|
|
85
117
|
##
|
@@ -87,11 +119,16 @@ module CarrierWave
|
|
87
119
|
# specified dimensions while retaining the aspect ratio of the original
|
88
120
|
# image. If necessary, crop the image in the larger dimension."
|
89
121
|
#
|
90
|
-
#
|
122
|
+
# See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
|
123
|
+
#
|
124
|
+
# === Parameters
|
91
125
|
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
126
|
+
# [width (Integer)] the width to scale the image to
|
127
|
+
# [height (Integer)] the height to scale the image to
|
128
|
+
#
|
129
|
+
# === Yields
|
130
|
+
#
|
131
|
+
# [Magick::Image] additional manipulations to perform
|
95
132
|
#
|
96
133
|
def resize_to_fill(width, height)
|
97
134
|
manipulate! do |img|
|
@@ -100,33 +137,40 @@ module CarrierWave
|
|
100
137
|
img
|
101
138
|
end
|
102
139
|
end
|
103
|
-
|
140
|
+
|
104
141
|
alias_method :crop_resized, :resize_to_fill
|
105
|
-
|
142
|
+
|
106
143
|
##
|
107
144
|
# Resize the image to fit within the specified dimensions while retaining
|
108
|
-
# the original aspect ratio. If necessary will pad the remaining area
|
145
|
+
# the original aspect ratio. If necessary, will pad the remaining area
|
109
146
|
# with the given color, which defaults to transparent (for gif and png,
|
110
147
|
# white for jpeg).
|
111
148
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
149
|
+
# === Parameters
|
150
|
+
#
|
151
|
+
# [width (Integer)] the width to scale the image to
|
152
|
+
# [height (Integer)] the height to scale the image to
|
153
|
+
# [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
|
154
|
+
# [gravity (Magick::GravityType)] how to position the image
|
155
|
+
#
|
156
|
+
# === Yields
|
157
|
+
#
|
158
|
+
# [Magick::Image] additional manipulations to perform
|
117
159
|
#
|
118
160
|
def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
|
119
161
|
manipulate! do |img|
|
120
162
|
img.resize_to_fit!(width, height)
|
121
163
|
new_img = ::Magick::Image.new(width, height)
|
122
164
|
if background == :transparent
|
123
|
-
|
165
|
+
filled = new_img.matte_floodfill(1, 1)
|
124
166
|
else
|
125
|
-
|
167
|
+
filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
|
126
168
|
end
|
127
|
-
new_img
|
128
|
-
|
129
|
-
|
169
|
+
new_img.destroy!
|
170
|
+
filled.composite!(img, gravity, ::Magick::OverCompositeOp)
|
171
|
+
img.destroy!
|
172
|
+
filled = yield(filled) if block_given?
|
173
|
+
filled
|
130
174
|
end
|
131
175
|
end
|
132
176
|
|
@@ -135,11 +179,20 @@ module CarrierWave
|
|
135
179
|
# and then pass each of its frames to the supplied block. It will then
|
136
180
|
# save the image to disk.
|
137
181
|
#
|
138
|
-
#
|
139
|
-
#
|
182
|
+
# === Gotcha
|
183
|
+
#
|
184
|
+
# This method assumes that the object responds to +current_path+.
|
185
|
+
# Any class that this module is mixed into must have a +current_path+ method.
|
186
|
+
# CarrierWave::Uploader does, so you won't need to worry about this in
|
187
|
+
# most cases.
|
188
|
+
#
|
189
|
+
# === Yields
|
140
190
|
#
|
141
|
-
#
|
142
|
-
#
|
191
|
+
# [Magick::Image] manipulations to perform
|
192
|
+
#
|
193
|
+
# === Raises
|
194
|
+
#
|
195
|
+
# [CarrierWave::ProcessingError] if manipulation failed.
|
143
196
|
#
|
144
197
|
def manipulate!
|
145
198
|
image = ::Magick::Image.read(current_path)
|
@@ -150,12 +203,15 @@ module CarrierWave
|
|
150
203
|
list << yield( frame )
|
151
204
|
end
|
152
205
|
list.write(current_path)
|
206
|
+
list.destroy!
|
153
207
|
else
|
154
|
-
|
208
|
+
frame = image.first
|
209
|
+
yield( frame ).write(current_path)
|
210
|
+
frame.destroy!
|
155
211
|
end
|
156
212
|
rescue ::Magick::ImageMagickError => e
|
157
213
|
raise CarrierWave::ProcessingError.new("Failed to manipulate with rmagick, maybe it is not an image? Original Error: #{e}")
|
158
|
-
end
|
159
|
-
|
214
|
+
end
|
215
|
+
|
160
216
|
end # RMagick
|
161
|
-
end # CarrierWave
|
217
|
+
end # CarrierWave
|
@@ -10,17 +10,18 @@ module CarrierWave
|
|
10
10
|
#
|
11
11
|
class SanitizedFile
|
12
12
|
|
13
|
-
attr_accessor :file
|
13
|
+
attr_accessor :file
|
14
14
|
|
15
|
-
def initialize(file
|
15
|
+
def initialize(file)
|
16
16
|
self.file = file
|
17
|
-
self.options = options
|
18
17
|
end
|
19
18
|
|
20
19
|
##
|
21
20
|
# Returns the filename as is, without sanizting it.
|
22
21
|
#
|
23
|
-
#
|
22
|
+
# === Returns
|
23
|
+
#
|
24
|
+
# [String] the unsanitized filename
|
24
25
|
#
|
25
26
|
def original_filename
|
26
27
|
return @original_filename if @original_filename
|
@@ -30,32 +31,38 @@ module CarrierWave
|
|
30
31
|
File.basename(path)
|
31
32
|
end
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
##
|
35
36
|
# Returns the filename, sanitized to strip out any evil characters.
|
36
37
|
#
|
37
|
-
#
|
38
|
+
# === Returns
|
39
|
+
#
|
40
|
+
# [String] the sanitized filename
|
38
41
|
#
|
39
42
|
def filename
|
40
43
|
sanitize(original_filename) if original_filename
|
41
44
|
end
|
42
|
-
|
45
|
+
|
43
46
|
alias_method :identifier, :filename
|
44
|
-
|
47
|
+
|
45
48
|
##
|
46
49
|
# Returns the part of the filename before the extension. So if a file is called 'test.jpeg'
|
47
50
|
# this would return 'test'
|
48
51
|
#
|
49
|
-
#
|
52
|
+
# === Returns
|
53
|
+
#
|
54
|
+
# [String] the first part of the filename
|
50
55
|
#
|
51
56
|
def basename
|
52
57
|
split_extension(filename)[0] if filename
|
53
58
|
end
|
54
|
-
|
59
|
+
|
55
60
|
##
|
56
61
|
# Returns the file extension
|
57
62
|
#
|
58
|
-
#
|
63
|
+
# === Returns
|
64
|
+
#
|
65
|
+
# [String] the extension
|
59
66
|
#
|
60
67
|
def extension
|
61
68
|
split_extension(filename)[1] if filename
|
@@ -64,16 +71,18 @@ module CarrierWave
|
|
64
71
|
##
|
65
72
|
# Returns the file's size.
|
66
73
|
#
|
67
|
-
#
|
74
|
+
# === Returns
|
75
|
+
#
|
76
|
+
# [Integer] the file's size in bytes.
|
68
77
|
#
|
69
78
|
def size
|
70
|
-
if
|
79
|
+
if is_path?
|
71
80
|
exists? ? File.size(path) : 0
|
72
81
|
elsif @file.respond_to?(:size)
|
73
|
-
@file.size
|
82
|
+
@file.size
|
74
83
|
elsif path
|
75
84
|
exists? ? File.size(path) : 0
|
76
|
-
else
|
85
|
+
else
|
77
86
|
0
|
78
87
|
end
|
79
88
|
end
|
@@ -81,53 +90,59 @@ module CarrierWave
|
|
81
90
|
##
|
82
91
|
# Returns the full path to the file. If the file has no path, it will return nil.
|
83
92
|
#
|
84
|
-
#
|
93
|
+
# === Returns
|
94
|
+
#
|
95
|
+
# [String, nil] the path where the file is located.
|
85
96
|
#
|
86
97
|
def path
|
87
98
|
unless @file.blank?
|
88
|
-
if
|
99
|
+
if is_path?
|
89
100
|
File.expand_path(@file)
|
90
101
|
elsif @file.respond_to?(:path) and not @file.path.blank?
|
91
102
|
File.expand_path(@file.path)
|
92
103
|
end
|
93
104
|
end
|
94
105
|
end
|
95
|
-
|
106
|
+
|
96
107
|
##
|
97
|
-
# Returns
|
108
|
+
# === Returns
|
98
109
|
#
|
99
|
-
#
|
110
|
+
# [Boolean] whether the file is supplied as a pathname or string.
|
100
111
|
#
|
101
|
-
def
|
112
|
+
def is_path?
|
102
113
|
!!((@file.is_a?(String) || @file.is_a?(Pathname)) && !@file.blank?)
|
103
114
|
end
|
104
115
|
|
105
116
|
##
|
106
|
-
#
|
117
|
+
# === Returns
|
107
118
|
#
|
108
|
-
#
|
119
|
+
# [Boolean] whether the file is valid and has a non-zero size
|
109
120
|
#
|
110
121
|
def empty?
|
111
122
|
@file.nil? || self.size.nil? || self.size.zero?
|
112
123
|
end
|
113
124
|
|
125
|
+
alias_method :blank?, :empty?
|
126
|
+
|
114
127
|
##
|
115
|
-
#
|
128
|
+
# === Returns
|
116
129
|
#
|
117
|
-
#
|
130
|
+
# [Boolean] Whether the file exists
|
118
131
|
#
|
119
132
|
def exists?
|
120
133
|
return File.exists?(self.path) if self.path
|
121
134
|
return false
|
122
135
|
end
|
123
|
-
|
136
|
+
|
124
137
|
##
|
125
138
|
# Returns the contents of the file.
|
126
139
|
#
|
127
|
-
#
|
140
|
+
# === Returns
|
141
|
+
#
|
142
|
+
# [String] contents of the file
|
128
143
|
#
|
129
144
|
def read
|
130
|
-
if
|
145
|
+
if is_path?
|
131
146
|
File.read(@file)
|
132
147
|
else
|
133
148
|
@file.rewind if @file.respond_to?(:rewind)
|
@@ -138,9 +153,12 @@ module CarrierWave
|
|
138
153
|
##
|
139
154
|
# Moves the file to the given path
|
140
155
|
#
|
141
|
-
#
|
156
|
+
# === Parameters
|
142
157
|
#
|
143
|
-
|
158
|
+
# [new_path (String)] The path where the file should be moved.
|
159
|
+
# [permissions (Integer)] permissions to set on the file in its new location.
|
160
|
+
#
|
161
|
+
def move_to(new_path, permissions=nil)
|
144
162
|
return if self.empty?
|
145
163
|
new_path = File.expand_path(new_path)
|
146
164
|
|
@@ -150,17 +168,23 @@ module CarrierWave
|
|
150
168
|
else
|
151
169
|
File.open(new_path, "wb") { |f| f.write(read) }
|
152
170
|
end
|
153
|
-
chmod!(new_path)
|
171
|
+
chmod!(new_path, permissions)
|
154
172
|
self.file = new_path
|
155
173
|
end
|
156
174
|
|
157
175
|
##
|
158
176
|
# Creates a copy of this file and moves it to the given path. Returns the copy.
|
159
177
|
#
|
160
|
-
#
|
178
|
+
# === Parameters
|
179
|
+
#
|
180
|
+
# [new_path (String)] The path where the file should be copied to.
|
181
|
+
# [permissions (Integer)] permissions to set on the copy
|
182
|
+
#
|
183
|
+
# === Returns
|
184
|
+
#
|
161
185
|
# @return [CarrierWave::SanitizedFile] the location where the file will be stored.
|
162
186
|
#
|
163
|
-
def copy_to(new_path)
|
187
|
+
def copy_to(new_path, permissions=nil)
|
164
188
|
return if self.empty?
|
165
189
|
new_path = File.expand_path(new_path)
|
166
190
|
|
@@ -170,7 +194,7 @@ module CarrierWave
|
|
170
194
|
else
|
171
195
|
File.open(new_path, "wb") { |f| f.write(read) }
|
172
196
|
end
|
173
|
-
chmod!(new_path)
|
197
|
+
chmod!(new_path, permissions)
|
174
198
|
self.class.new(new_path)
|
175
199
|
end
|
176
200
|
|
@@ -184,7 +208,9 @@ module CarrierWave
|
|
184
208
|
##
|
185
209
|
# Returns the content type of the file.
|
186
210
|
#
|
187
|
-
#
|
211
|
+
# === Returns
|
212
|
+
#
|
213
|
+
# [String] the content type of the file
|
188
214
|
#
|
189
215
|
def content_type
|
190
216
|
return @content_type if @content_type
|
@@ -192,26 +218,26 @@ module CarrierWave
|
|
192
218
|
end
|
193
219
|
|
194
220
|
private
|
195
|
-
|
221
|
+
|
196
222
|
def file=(file)
|
197
223
|
if file.is_a?(Hash)
|
198
|
-
@file = file["tempfile"]
|
199
|
-
@original_filename = file["filename"]
|
200
|
-
@content_type = file["content_type"]
|
224
|
+
@file = file["tempfile"] || file[:tempfile]
|
225
|
+
@original_filename = file["filename"] || file[:filename]
|
226
|
+
@content_type = file["content_type"] || file[:content_type]
|
201
227
|
else
|
202
228
|
@file = file
|
203
229
|
@original_filename = nil
|
204
230
|
@content_type = nil
|
205
231
|
end
|
206
232
|
end
|
207
|
-
|
233
|
+
|
208
234
|
# create the directory if it doesn't exist
|
209
235
|
def mkdir!(path)
|
210
236
|
FileUtils.mkdir_p(File.dirname(path)) unless File.exists?(File.dirname(path))
|
211
237
|
end
|
212
|
-
|
213
|
-
def chmod!(path)
|
214
|
-
File.chmod(
|
238
|
+
|
239
|
+
def chmod!(path, permissions)
|
240
|
+
File.chmod(permissions, path) if permissions
|
215
241
|
end
|
216
242
|
|
217
243
|
# Sanitize the filename, to prevent hacking
|
@@ -219,16 +245,16 @@ module CarrierWave
|
|
219
245
|
name = name.gsub("\\", "/") # work-around for IE
|
220
246
|
name = File.basename(name)
|
221
247
|
name = name.gsub(/[^a-zA-Z0-9\.\-\+_]/,"_")
|
222
|
-
name = "_#{name}" if name =~
|
248
|
+
name = "_#{name}" if name =~ /\A\.+\z/
|
223
249
|
name = "unnamed" if name.size == 0
|
224
250
|
return name.downcase
|
225
251
|
end
|
226
252
|
|
227
253
|
def split_extension(fn)
|
228
254
|
# regular expressions to try for identifying extensions
|
229
|
-
ext_regexps = [
|
230
|
-
|
231
|
-
|
255
|
+
ext_regexps = [
|
256
|
+
/\A(.+)\.([^\.]{1,3}\.[^\.]{1,4})\z/, # matches "something.tar.gz"
|
257
|
+
/\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
|
232
258
|
]
|
233
259
|
ext_regexps.each do |regexp|
|
234
260
|
if fn =~ regexp
|
@@ -239,4 +265,4 @@ module CarrierWave
|
|
239
265
|
end
|
240
266
|
|
241
267
|
end # SanitizedFile
|
242
|
-
end # CarrierWave
|
268
|
+
end # CarrierWave
|