jnicklas-carrierwave 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- # MyUploade < CarrierWave::Uploader
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
- # MyUploade < CarrierWave::Uploader
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
- # MyUploade < CarrierWave::Uploader
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
- # @see http://www.imagemagick.org/RMagick/doc/magick.html#formats
50
- # @param [#to_s] format an abreviation of the format
51
- # @yieldparam [Magick::Image] img additional manipulations to perform
52
- # @example
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
- # @see http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
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
- # @see http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
122
+ # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
123
+ #
124
+ # === Parameters
91
125
  #
92
- # @param [Integer] width the width to scale the image to
93
- # @param [Integer] height the height to scale the image to
94
- # @yieldparam [Magick::Image] img additional manipulations to perform
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
- # @param [Integer] width the width to scale the image to
113
- # @param [Integer] height the height to scale the image to
114
- # @param [String, :transparent] background the color of the background as a hexcode, like "#ff45de"
115
- # @param [Magick::GravityType] gravity how to position the image
116
- # @yieldparam [Magick::Image] img additional manipulations to perform
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
- new_img = new_img.matte_floodfill(1, 1)
165
+ filled = new_img.matte_floodfill(1, 1)
124
166
  else
125
- new_img = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
167
+ filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
126
168
  end
127
- new_img = new_img.composite(img, gravity, ::Magick::OverCompositeOp)
128
- new_img = yield(new_img) if block_given?
129
- new_img
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
- # Note: This method assumes that the object responds to current_path
139
- # any class that this is mixed into must have a current_path method.
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
- # @yieldparam [Magick::Image] img manipulations to perform
142
- # @raise [CarrierWave::ProcessingError] if manipulation failed.
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
- yield( image.first ).write(current_path)
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, :options
13
+ attr_accessor :file
14
14
 
15
- def initialize(file, options = {})
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
- # @return [String] the unsanitized filename
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
- # @return [String] the sanitized filename
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
- # @return [String] the first part of the filename
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
- # @return [String] the extension
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
- # @return [Integer] the file's size in bytes.
74
+ # === Returns
75
+ #
76
+ # [Integer] the file's size in bytes.
68
77
  #
69
78
  def size
70
- if string?
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
- # @return [String, nil] the path where the file is located.
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 string?
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 true if the file is supplied as a pathname or as a string.
108
+ # === Returns
98
109
  #
99
- # @return [Boolean]
110
+ # [Boolean] whether the file is supplied as a pathname or string.
100
111
  #
101
- def string?
112
+ def is_path?
102
113
  !!((@file.is_a?(String) || @file.is_a?(Pathname)) && !@file.blank?)
103
114
  end
104
115
 
105
116
  ##
106
- # Checks if the file is valid and has a non-zero size
117
+ # === Returns
107
118
  #
108
- # @return [Boolean]
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
- # Checks if the file exists
128
+ # === Returns
116
129
  #
117
- # @return [Boolean]
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
- # @return [String] contents of the file
140
+ # === Returns
141
+ #
142
+ # [String] contents of the file
128
143
  #
129
144
  def read
130
- if string?
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
- # @param [String] new_path The path where the file should be moved.
156
+ # === Parameters
142
157
  #
143
- def move_to(new_path)
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
- # @param [String] new_path The path where the file should be copied to.
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
- # @return [String] the content type of the file
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(@options[:permissions], path) if @options[:permissions]
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
@@ -226,7 +252,7 @@ module CarrierWave
226
252
 
227
253
  def split_extension(fn)
228
254
  # regular expressions to try for identifying extensions
229
- ext_regexps = [
255
+ ext_regexps = [
230
256
  /\A(.+)\.([^\.]{1,3}\.[^\.]{1,4})\z/, # matches "something.tar.gz"
231
257
  /\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
232
258
  ]
@@ -239,4 +265,4 @@ module CarrierWave
239
265
  end
240
266
 
241
267
  end # SanitizedFile
242
- end # CarrierWave
268
+ end # CarrierWave
@@ -27,10 +27,14 @@ module CarrierWave
27
27
  ##
28
28
  # Do something to store the file
29
29
  #
30
- # @param [CarrierWave::Uploader] uploader an uploader object
31
- # @param [CarrierWave::SanitizedFile] file the file to store
30
+ # === Parameters
32
31
  #
33
- # @return [#identifier] an object
32
+ # [uploader (CarrierWave::Uploader)] an uploader object
33
+ # [file (CarrierWave::SanitizedFile)] the file to store
34
+ #
35
+ # === Returns
36
+ #
37
+ # [#identifier] an object
34
38
  #
35
39
  def self.store!(uploader, file)
36
40
  self.new
@@ -38,10 +42,14 @@ module CarrierWave
38
42
 
39
43
  # Do something to retrieve the file
40
44
  #
41
- # @param [CarrierWave::Uploader] uploader an uploader object
42
- # @param [String] identifier uniquely identifies the file
45
+ # === Parameters
46
+ #
47
+ # [uploader (CarrierWave::Uploader)] an uploader object
48
+ # [identifier (String)] uniquely identifies the file
49
+ #
50
+ # === Returns
43
51
  #
44
- # @return [#identifier] an object
52
+ # [#identifier] an object
45
53
  #
46
54
  def self.retrieve!(uploader, identifier)
47
55
  self.new
@@ -53,7 +61,9 @@ module CarrierWave
53
61
  #
54
62
  # This is OPTIONAL
55
63
  #
56
- # @return [String] path to the file
64
+ # === Returns
65
+ #
66
+ # [String] path to the file
57
67
  #
58
68
  def identifier; end
59
69
 
@@ -63,7 +73,9 @@ module CarrierWave
63
73
  #
64
74
  # This is OPTIONAL
65
75
  #
66
- # @return [String] file's url
76
+ # === Returns
77
+ #
78
+ # [String] file's url
67
79
  #
68
80
  def url; end
69
81
 
@@ -72,7 +84,9 @@ module CarrierWave
72
84
  #
73
85
  # This is OPTIONAL
74
86
  #
75
- # @return [String] path to the file
87
+ # === Returns
88
+ #
89
+ # [String] path to the file
76
90
  #
77
91
  def path; end
78
92
 
@@ -15,28 +15,36 @@ module CarrierWave
15
15
  ##
16
16
  # Move the file to the uploader's store path.
17
17
  #
18
- # @param [CarrierWave::Uploader] uploader an uploader object
19
- # @param [CarrierWave::SanitizedFile] file the file to store
18
+ # === Parameters
20
19
  #
21
- # @return [CarrierWave::SanitizedFile] a sanitized file
20
+ # [uploader (CarrierWave::Uploader)] an uploader object
21
+ # [file (CarrierWave::SanitizedFile)] the file to store
22
+ #
23
+ # === Returns
24
+ #
25
+ # [CarrierWave::SanitizedFile] a sanitized file
22
26
  #
23
27
  def self.store!(uploader, file)
24
- path = ::File.join(uploader.store_dir, uploader.filename)
28
+ path = ::File.join(uploader.store_path)
25
29
  path = ::File.expand_path(path, uploader.public)
26
- file.move_to(path)
30
+ file.move_to(path, CarrierWave.config[:permissions])
27
31
  file
28
32
  end
29
33
 
30
34
  ##
31
35
  # Retrieve the file from its store path
32
36
  #
33
- # @param [CarrierWave::Uploader] uploader an uploader object
34
- # @param [String] identifier the filename of the file
37
+ # === Parameters
38
+ #
39
+ # [uploader (CarrierWave::Uploader)] an uploader object
40
+ # [identifier (String)] the filename of the file
41
+ #
42
+ # === Returns
35
43
  #
36
- # @return [CarrierWave::SanitizedFile] a sanitized file
44
+ # [CarrierWave::SanitizedFile] a sanitized file
37
45
  #
38
46
  def self.retrieve!(uploader, identifier)
39
- path = ::File.join(uploader.store_dir, identifier)
47
+ path = ::File.join(uploader.store_path(identifier))
40
48
  path = ::File.expand_path(path, uploader.public)
41
49
  CarrierWave::SanitizedFile.new(path)
42
50
  end