samlown-carrierwave 0.4.5

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.
Files changed (111) hide show
  1. data/Generators +4 -0
  2. data/History.txt +125 -0
  3. data/Manifest.txt +110 -0
  4. data/README.rdoc +524 -0
  5. data/Rakefile +39 -0
  6. data/carrierwave.gemspec +85 -0
  7. data/cucumber.yml +2 -0
  8. data/features/caching.feature +28 -0
  9. data/features/download.feature +20 -0
  10. data/features/file_storage.feature +37 -0
  11. data/features/file_storage_overridden_filename.feature +38 -0
  12. data/features/file_storage_overridden_store_dir.feature +38 -0
  13. data/features/file_storage_reversing_processor.feature +43 -0
  14. data/features/fixtures/bork.txt +1 -0
  15. data/features/fixtures/monkey.txt +1 -0
  16. data/features/grid_fs_storage.feature +32 -0
  17. data/features/mount_activerecord.feature +46 -0
  18. data/features/mount_datamapper.feature +46 -0
  19. data/features/step_definitions/activerecord_steps.rb +22 -0
  20. data/features/step_definitions/caching_steps.rb +14 -0
  21. data/features/step_definitions/datamapper_steps.rb +29 -0
  22. data/features/step_definitions/download_steps.rb +4 -0
  23. data/features/step_definitions/file_steps.rb +53 -0
  24. data/features/step_definitions/general_steps.rb +85 -0
  25. data/features/step_definitions/mount_steps.rb +19 -0
  26. data/features/step_definitions/store_steps.rb +18 -0
  27. data/features/support/activerecord.rb +30 -0
  28. data/features/support/datamapper.rb +7 -0
  29. data/features/support/env.rb +22 -0
  30. data/features/versions_basics.feature +50 -0
  31. data/features/versions_nested_versions.feature +70 -0
  32. data/features/versions_overridden_filename.feature +51 -0
  33. data/features/versions_overriden_store_dir.feature +41 -0
  34. data/lib/carrierwave.rb +98 -0
  35. data/lib/carrierwave/compatibility/paperclip.rb +95 -0
  36. data/lib/carrierwave/core_ext/blank.rb +46 -0
  37. data/lib/carrierwave/core_ext/file.rb +11 -0
  38. data/lib/carrierwave/core_ext/inheritable_attributes.rb +108 -0
  39. data/lib/carrierwave/core_ext/module_setup.rb +51 -0
  40. data/lib/carrierwave/mount.rb +359 -0
  41. data/lib/carrierwave/orm/activerecord.rb +73 -0
  42. data/lib/carrierwave/orm/datamapper.rb +27 -0
  43. data/lib/carrierwave/orm/mongoid.rb +23 -0
  44. data/lib/carrierwave/orm/mongomapper.rb +27 -0
  45. data/lib/carrierwave/orm/sequel.rb +45 -0
  46. data/lib/carrierwave/processing/image_science.rb +101 -0
  47. data/lib/carrierwave/processing/mini_magick.rb +265 -0
  48. data/lib/carrierwave/processing/rmagick.rb +282 -0
  49. data/lib/carrierwave/sanitized_file.rb +273 -0
  50. data/lib/carrierwave/storage/abstract.rb +30 -0
  51. data/lib/carrierwave/storage/cloud_files.rb +169 -0
  52. data/lib/carrierwave/storage/file.rb +48 -0
  53. data/lib/carrierwave/storage/grid_fs.rb +97 -0
  54. data/lib/carrierwave/storage/right_s3.rb +3 -0
  55. data/lib/carrierwave/storage/s3.rb +206 -0
  56. data/lib/carrierwave/test/matchers.rb +128 -0
  57. data/lib/carrierwave/uploader.rb +44 -0
  58. data/lib/carrierwave/uploader/cache.rb +145 -0
  59. data/lib/carrierwave/uploader/callbacks.rb +42 -0
  60. data/lib/carrierwave/uploader/configuration.rb +132 -0
  61. data/lib/carrierwave/uploader/default_url.rb +19 -0
  62. data/lib/carrierwave/uploader/download.rb +59 -0
  63. data/lib/carrierwave/uploader/extension_whitelist.rb +37 -0
  64. data/lib/carrierwave/uploader/mountable.rb +39 -0
  65. data/lib/carrierwave/uploader/processing.rb +83 -0
  66. data/lib/carrierwave/uploader/proxy.rb +62 -0
  67. data/lib/carrierwave/uploader/remove.rb +22 -0
  68. data/lib/carrierwave/uploader/store.rb +89 -0
  69. data/lib/carrierwave/uploader/url.rb +33 -0
  70. data/lib/carrierwave/uploader/versions.rb +146 -0
  71. data/merb_generators/uploader_generator.rb +22 -0
  72. data/rails_generators/uploader/USAGE +2 -0
  73. data/rails_generators/uploader/templates/uploader.rb +47 -0
  74. data/rails_generators/uploader/uploader_generator.rb +21 -0
  75. data/script/console +10 -0
  76. data/script/destroy +14 -0
  77. data/script/generate +14 -0
  78. data/spec/compatibility/paperclip_spec.rb +52 -0
  79. data/spec/fixtures/bork.txt +1 -0
  80. data/spec/fixtures/landscape.jpg +0 -0
  81. data/spec/fixtures/portrait.jpg +0 -0
  82. data/spec/fixtures/test.jpeg +1 -0
  83. data/spec/fixtures/test.jpg +1 -0
  84. data/spec/mount_spec.rb +538 -0
  85. data/spec/orm/activerecord_spec.rb +271 -0
  86. data/spec/orm/datamapper_spec.rb +168 -0
  87. data/spec/orm/mongoid_spec.rb +202 -0
  88. data/spec/orm/mongomapper_spec.rb +202 -0
  89. data/spec/orm/sequel_spec.rb +183 -0
  90. data/spec/processing/image_science_spec.rb +56 -0
  91. data/spec/processing/mini_magick_spec.rb +76 -0
  92. data/spec/processing/rmagick_spec.rb +75 -0
  93. data/spec/sanitized_file_spec.rb +623 -0
  94. data/spec/spec_helper.rb +92 -0
  95. data/spec/storage/cloudfiles_spec.rb +78 -0
  96. data/spec/storage/grid_fs_spec.rb +83 -0
  97. data/spec/storage/s3_spec.rb +118 -0
  98. data/spec/uploader/cache_spec.rb +209 -0
  99. data/spec/uploader/configuration_spec.rb +105 -0
  100. data/spec/uploader/default_url_spec.rb +85 -0
  101. data/spec/uploader/download_spec.rb +75 -0
  102. data/spec/uploader/extension_whitelist_spec.rb +44 -0
  103. data/spec/uploader/mountable_spec.rb +33 -0
  104. data/spec/uploader/paths_spec.rb +22 -0
  105. data/spec/uploader/processing_spec.rb +73 -0
  106. data/spec/uploader/proxy_spec.rb +54 -0
  107. data/spec/uploader/remove_spec.rb +70 -0
  108. data/spec/uploader/store_spec.rb +264 -0
  109. data/spec/uploader/url_spec.rb +102 -0
  110. data/spec/uploader/versions_spec.rb +298 -0
  111. metadata +433 -0
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ require 'mongoid'
3
+
4
+ module CarrierWave
5
+ module Mongoid
6
+ include CarrierWave::Mount
7
+ ##
8
+ # See +CarrierWave::Mount#mount_uploader+ for documentation
9
+ #
10
+ def mount_uploader(column, uploader, options={}, &block)
11
+ options[:mount_on] ||= "#{column}_filename"
12
+ field options[:mount_on]
13
+ super
14
+ alias_method :read_uploader, :read_attribute
15
+ alias_method :write_uploader, :write_attribute
16
+ after_save "store_#{column}!".to_sym
17
+ before_save "write_#{column}_identifier".to_sym
18
+ after_destroy "remove_#{column}!".to_sym
19
+ end
20
+ end # Mongoid
21
+ end # CarrierWave
22
+
23
+ Mongoid::Document::ClassMethods.send(:include, CarrierWave::Mongoid)
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ require 'mongo_mapper'
3
+
4
+ module CarrierWave
5
+ module MongoMapper
6
+ include CarrierWave::Mount
7
+ ##
8
+ # See +CarrierWave::Mount#mount_uploader+ for documentation
9
+ #
10
+ def mount_uploader(column, uploader, options={}, &block)
11
+ # We need to set the mount_on column (or key in MongoMapper's case)
12
+ # since MongoMapper will attempt to set the filename on
13
+ # the uploader instead of the file on a Document's initialization.
14
+ options[:mount_on] ||= "#{column}_filename"
15
+ key options[:mount_on]
16
+
17
+ super
18
+ alias_method :read_uploader, :[]
19
+ alias_method :write_uploader, :[]=
20
+ after_save "store_#{column}!".to_sym
21
+ before_save "write_#{column}_identifier".to_sym
22
+ after_destroy "remove_#{column}!".to_sym
23
+ end
24
+ end # MongoMapper
25
+ end # CarrierWave
26
+
27
+ MongoMapper::Document::ClassMethods.send(:include, CarrierWave::MongoMapper)
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'sequel'
4
+
5
+ module CarrierWave
6
+ module Sequel
7
+ include CarrierWave::Mount
8
+
9
+ def mount_uploader(column, uploader)
10
+ raise "You need to use Sequel 3.0 or higher. Please upgrade." unless ::Sequel::Model.respond_to?(:plugin)
11
+ super
12
+
13
+ alias_method :read_uploader, :[]
14
+ alias_method :write_uploader, :[]=
15
+
16
+ include CarrierWave::Sequel::Hooks
17
+ include CarrierWave::Sequel::Validations
18
+ end
19
+
20
+ end # Sequel
21
+ end # CarrierWave
22
+
23
+ # Instance hook methods for the Sequel 3.x
24
+ module CarrierWave::Sequel::Hooks
25
+ def after_save
26
+ return false if super == false
27
+ self.class.uploaders.each_key {|column| self.send("store_#{column}!") }
28
+ end
29
+
30
+ def before_save
31
+ return false if super == false
32
+ self.class.uploaders.each_key {|column| self.send("write_#{column}_identifier") }
33
+ end
34
+
35
+ def before_destroy
36
+ return false if super == false
37
+ self.class.uploaders.each_key {|column| self.send("remove_#{column}!") }
38
+ end
39
+ end
40
+
41
+ # Instance validation methods for the Sequel 3.x
42
+ module CarrierWave::Sequel::Validations
43
+ end
44
+
45
+ Sequel::Model.send(:extend, CarrierWave::Sequel)
@@ -0,0 +1,101 @@
1
+ # encoding: utf-8
2
+
3
+ require "image_science"
4
+
5
+ module CarrierWave
6
+ module ImageScience
7
+
8
+ ##
9
+ # Resize the image to fit within the specified dimensions while retaining
10
+ # the original aspect ratio. The image may be shorter or narrower than
11
+ # specified in the smaller dimension but will not be larger than the
12
+ # specified values.
13
+ #
14
+ # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
15
+ #
16
+ # === Parameters
17
+ #
18
+ # [width (Integer)] the width to scale the image to
19
+ # [height (Integer)] the height to scale the image to
20
+ #
21
+ def resize_to_fit(new_width, new_height)
22
+ ::ImageScience.with_image(self.current_path) do |img|
23
+ width, height = extract_dimensions(img.width, img.height, new_width, new_height)
24
+ img.resize( width, height ) do |file|
25
+ file.save( self.current_path )
26
+ end
27
+ end
28
+ end
29
+
30
+ ##
31
+ # Resize the image to fit within the specified dimensions while retaining
32
+ # the aspect ratio of the original image. If necessary, crop the image in
33
+ # the larger dimension.
34
+ #
35
+ # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
36
+ #
37
+ # === Parameters
38
+ #
39
+ # [width (Integer)] the width to scale the image to
40
+ # [height (Integer)] the height to scale the image to
41
+ #
42
+ def resize_to_fill(new_width, new_height)
43
+ ::ImageScience.with_image(self.current_path) do |img|
44
+ width, height = extract_dimensions_for_crop(img.width, img.height, new_width, new_height)
45
+ x_offset, y_offset = extract_placement_for_crop(width, height, new_width, new_height)
46
+
47
+ img.resize( width, height ) do |i2|
48
+
49
+ i2.with_crop( x_offset, y_offset, new_width + x_offset, new_height + y_offset) do |file|
50
+ file.save( self.current_path )
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ ##
57
+ # Resize the image to fit within the specified dimensions while retaining
58
+ # the original aspect ratio. Will only resize the image if it is larger than the
59
+ # specified dimensions. The resulting image may be shorter or narrower than specified
60
+ # in the smaller dimension but will not be larger than the specified values.
61
+ #
62
+ # === Parameters
63
+ #
64
+ # [width (Integer)] the width to scale the image to
65
+ # [height (Integer)] the height to scale the image to
66
+ #
67
+ def resize_to_limit(new_width, new_height)
68
+ ::ImageScience.with_image(self.current_path) do |img|
69
+ if img.width > new_width or img.height > new_height
70
+ resize_to_fit(new_width, new_height)
71
+ end
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def extract_dimensions(width, height, new_width, new_height, type = :resize)
78
+ aspect_ratio = width.to_f / height.to_f
79
+ new_aspect_ratio = new_width / new_height
80
+
81
+ if (new_aspect_ratio > aspect_ratio) ^ ( type == :crop ) # Image is too wide, the caret is the XOR operator
82
+ new_width, new_height = [ (new_height * aspect_ratio), new_height]
83
+ else #Image is too narrow
84
+ new_width, new_height = [ new_width, (new_width / aspect_ratio)]
85
+ end
86
+
87
+ [new_width, new_height].collect! { |v| v.round }
88
+ end
89
+
90
+ def extract_dimensions_for_crop(width, height, new_width, new_height)
91
+ extract_dimensions(width, height, new_width, new_height, :crop)
92
+ end
93
+
94
+ def extract_placement_for_crop(width, height, new_width, new_height)
95
+ x_offset = (width / 2.0) - (new_width / 2.0)
96
+ y_offset = (height / 2.0) - (new_height / 2.0)
97
+ [x_offset, y_offset].collect! { |v| v.round }
98
+ end
99
+
100
+ end # ImageScience
101
+ end # CarrierWave
@@ -0,0 +1,265 @@
1
+ # encoding: utf-8
2
+
3
+ require 'mini_magick'
4
+
5
+ module CarrierWave
6
+
7
+ ##
8
+ # This module simplifies manipulation with MiniMagick by providing a set
9
+ # of convenient helper methods. If you want to use them, you'll need to
10
+ # require this file:
11
+ #
12
+ # require 'carrierwave/processing/mini_magick'
13
+ #
14
+ # And then include it in your uploader:
15
+ #
16
+ # class MyUploader < CarrierWave::Uploader::Base
17
+ # include CarrierWave::MiniMagick
18
+ # end
19
+ #
20
+ # You can now use the provided helpers:
21
+ #
22
+ # class MyUploader < CarrierWave::Uploader::Base
23
+ # include CarrierWave::MiniMagick
24
+ #
25
+ # process :resize_to_fit => [200, 200]
26
+ # end
27
+ #
28
+ # Or create your own helpers with the powerful manipulate! method. Check
29
+ # out the ImageMagick docs at http://www.imagemagick.org/script/command-line-options.php for more
30
+ # info
31
+ #
32
+ # class MyUploader < CarrierWave::Uploader::Base
33
+ # include CarrierWave::MiniMagick
34
+ #
35
+ # process :do_stuff => 10.0
36
+ #
37
+ # def do_stuff(blur_factor)
38
+ # manipulate! do |img|
39
+ # img = img.sepiatone
40
+ # img = img.auto_orient
41
+ # img = img.radial_blur blur_factor
42
+ # end
43
+ # end
44
+ # end
45
+ #
46
+ # === Note
47
+ #
48
+ # MiniMagick is a mini replacement for RMagick that uses the command line
49
+ # tool "mogrify" for image manipulation.
50
+ #
51
+ # You can find more information here:
52
+ #
53
+ # http://mini_magick.rubyforge.org/
54
+ # and
55
+ # http://github.com/probablycorey/mini_magick/
56
+ #
57
+ #
58
+ module MiniMagick
59
+
60
+ def self.included(base)
61
+ super
62
+ base.extend(ClassMethods)
63
+ end
64
+
65
+ module ClassMethods
66
+ def convert(format)
67
+ process :convert => format
68
+ end
69
+
70
+ def resize_to_limit(width, height)
71
+ process :resize_to_limit => [width, height]
72
+ end
73
+
74
+ def resize_to_fit(width, height)
75
+ process :resize_to_fit => [width, height]
76
+ end
77
+
78
+ def resize_to_fill(width, height)
79
+ process :resize_to_fill => [width, height]
80
+ end
81
+
82
+ def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
83
+ process :resize_and_pad => [width, height, background, gravity]
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Changes the image encoding format to the given format
89
+ #
90
+ # See http://www.imagemagick.org/script/command-line-options.php#format
91
+ #
92
+ # === Parameters
93
+ #
94
+ # [format (#to_s)] an abreviation of the format
95
+ #
96
+ # === Yields
97
+ #
98
+ # [MiniMagick::Image] additional manipulations to perform
99
+ #
100
+ # === Examples
101
+ #
102
+ # image.convert(:png)
103
+ #
104
+ def convert(format)
105
+ manipulate! do |img|
106
+ img.format(format.to_s.upcase)
107
+ img = yield(img) if block_given?
108
+ img
109
+ end
110
+ end
111
+
112
+ ##
113
+ # Resize the image to fit within the specified dimensions while retaining
114
+ # the original aspect ratio. Will only resize the image if it is larger than the
115
+ # specified dimensions. The resulting image may be shorter or narrower than specified
116
+ # in the smaller dimension but will not be larger than the specified values.
117
+ #
118
+ # === Parameters
119
+ #
120
+ # [width (Integer)] the width to scale the image to
121
+ # [height (Integer)] the height to scale the image to
122
+ #
123
+ # === Yields
124
+ #
125
+ # [MiniMagick::Image] additional manipulations to perform
126
+ #
127
+ def resize_to_limit(width, height)
128
+ manipulate! do |img|
129
+ img.resize "#{width}x#{height}>"
130
+ img = yield(img) if block_given?
131
+ img
132
+ end
133
+ end
134
+
135
+ ##
136
+ # From the RMagick documentation: "Resize the image to fit within the
137
+ # specified dimensions while retaining the original aspect ratio. The
138
+ # image may be shorter or narrower than specified in the smaller dimension
139
+ # but will not be larger than the specified values."
140
+ #
141
+ # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
142
+ #
143
+ # === Parameters
144
+ #
145
+ # [width (Integer)] the width to scale the image to
146
+ # [height (Integer)] the height to scale the image to
147
+ #
148
+ # === Yields
149
+ #
150
+ # [MiniMagick::Image] additional manipulations to perform
151
+ #
152
+ def resize_to_fit(width, height)
153
+ manipulate! do |img|
154
+ img.resize "#{width}x#{height}"
155
+ img = yield(img) if block_given?
156
+ img
157
+ end
158
+ end
159
+
160
+ ##
161
+ # From the RMagick documentation: "Resize the image to fit within the
162
+ # specified dimensions while retaining the aspect ratio of the original
163
+ # image. If necessary, crop the image in the larger dimension."
164
+ #
165
+ # See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
166
+ #
167
+ # and
168
+ #
169
+ # http://www.clipclip.org/clips/detail/4365/jerrett-net-»-crop_resized-in-rmagick
170
+ #
171
+ # === Parameters
172
+ #
173
+ # [width (Integer)] the width to scale the image to
174
+ # [height (Integer)] the height to scale the image to
175
+ #
176
+ # === Yields
177
+ #
178
+ # [MiniMagick::Image] additional manipulations to perform
179
+ #
180
+ def resize_to_fill(width, height, gravity = 'Center')
181
+ manipulate! do |img|
182
+ cols, rows = img[:dimensions]
183
+ img.combine_options do |cmd|
184
+ if width != cols || height != rows
185
+ scale = [width/cols.to_f, height/rows.to_f].max
186
+ cols = (scale * (cols + 0.5)).round
187
+ rows = (scale * (rows + 0.5)).round
188
+ cmd.resize "#{cols}x#{rows}"
189
+ end
190
+ cmd.gravity gravity
191
+ cmd.extent "#{width}x#{height}" if cols != width || rows != height
192
+ end
193
+ img = yield(img) if block_given?
194
+ img
195
+ end
196
+ end
197
+
198
+ ##
199
+ # Resize the image to fit within the specified dimensions while retaining
200
+ # the original aspect ratio. If necessary, will pad the remaining area
201
+ # with the given color, which defaults to transparent (for gif and png,
202
+ # white for jpeg).
203
+ #
204
+ # See http://www.imagemagick.org/script/command-line-options.php#gravity
205
+ # for gravity options.
206
+ #
207
+ # === Parameters
208
+ #
209
+ # [width (Integer)] the width to scale the image to
210
+ # [height (Integer)] the height to scale the image to
211
+ # [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
212
+ # [gravity (String)] how to position the image
213
+ #
214
+ # === Yields
215
+ #
216
+ # [MiniMagick::Image] additional manipulations to perform
217
+ #
218
+ def resize_and_pad(width, height, background=:transparent, gravity='Center')
219
+ manipulate! do |img|
220
+ img.combine_options do |cmd|
221
+ cmd.thumbnail "#{width}x#{height}>"
222
+ if background == :transparent
223
+ cmd.background "rgba(0, 0, 0, 0.0)"
224
+ else
225
+ cmd.background background
226
+ end
227
+ cmd.gravity gravity
228
+ cmd.extent "#{width}x#{height}"
229
+ end
230
+ img = yield(img) if block_given?
231
+ img
232
+ end
233
+ end
234
+
235
+ ##
236
+ # Manipulate the image with RMagick. This method will load up an image
237
+ # and then pass each of its frames to the supplied block. It will then
238
+ # save the image to disk.
239
+ #
240
+ # === Gotcha
241
+ #
242
+ # This method assumes that the object responds to +current_path+.
243
+ # Any class that this module is mixed into must have a +current_path+ method.
244
+ # CarrierWave::Uploader does, so you won't need to worry about this in
245
+ # most cases.
246
+ #
247
+ # === Yields
248
+ #
249
+ # [MiniMagick::Image] manipulations to perform
250
+ #
251
+ # === Raises
252
+ #
253
+ # [CarrierWave::ProcessingError] if manipulation failed.
254
+ #
255
+ def manipulate!
256
+ image = ::MiniMagick::Image.from_file(current_path)
257
+ image = yield(image)
258
+ image.write(current_path)
259
+ ::MiniMagick::Image.from_file(current_path)
260
+ rescue ::MiniMagick::MiniMagickError => e
261
+ raise CarrierWave::ProcessingError.new("Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: #{e}")
262
+ end
263
+
264
+ end # MiniMagick
265
+ end # CarrierWave