andrewtimberlake-carrierwave 0.3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/Generators +4 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +314 -0
  4. data/Rakefile +29 -0
  5. data/lib/carrierwave.rb +140 -0
  6. data/lib/carrierwave/compatibility/paperclip.rb +95 -0
  7. data/lib/carrierwave/core_ext/blank.rb +46 -0
  8. data/lib/carrierwave/core_ext/inheritable_attributes.rb +104 -0
  9. data/lib/carrierwave/core_ext/module_setup.rb +51 -0
  10. data/lib/carrierwave/mount.rb +332 -0
  11. data/lib/carrierwave/orm/activerecord.rb +73 -0
  12. data/lib/carrierwave/orm/datamapper.rb +27 -0
  13. data/lib/carrierwave/orm/sequel.rb +57 -0
  14. data/lib/carrierwave/processing/image_science.rb +72 -0
  15. data/lib/carrierwave/processing/rmagick.rb +286 -0
  16. data/lib/carrierwave/sanitized_file.rb +272 -0
  17. data/lib/carrierwave/storage/abstract.rb +32 -0
  18. data/lib/carrierwave/storage/file.rb +50 -0
  19. data/lib/carrierwave/storage/s3.rb +215 -0
  20. data/lib/carrierwave/test/matchers.rb +114 -0
  21. data/lib/carrierwave/uploader.rb +43 -0
  22. data/lib/carrierwave/uploader/cache.rb +116 -0
  23. data/lib/carrierwave/uploader/callbacks.rb +42 -0
  24. data/lib/carrierwave/uploader/default_path.rb +23 -0
  25. data/lib/carrierwave/uploader/extension_whitelist.rb +37 -0
  26. data/lib/carrierwave/uploader/mountable.rb +39 -0
  27. data/lib/carrierwave/uploader/paths.rb +27 -0
  28. data/lib/carrierwave/uploader/processing.rb +81 -0
  29. data/lib/carrierwave/uploader/proxy.rb +62 -0
  30. data/lib/carrierwave/uploader/remove.rb +23 -0
  31. data/lib/carrierwave/uploader/store.rb +156 -0
  32. data/lib/carrierwave/uploader/url.rb +24 -0
  33. data/lib/carrierwave/uploader/versions.rb +147 -0
  34. data/lib/generators/uploader_generator.rb +22 -0
  35. data/rails_generators/uploader/USAGE +2 -0
  36. data/rails_generators/uploader/templates/uploader.rb +47 -0
  37. data/rails_generators/uploader/uploader_generator.rb +21 -0
  38. data/spec/compatibility/paperclip_spec.rb +43 -0
  39. data/spec/fixtures/bork.txt +1 -0
  40. data/spec/fixtures/test.jpeg +1 -0
  41. data/spec/fixtures/test.jpg +1 -0
  42. data/spec/mount_spec.rb +517 -0
  43. data/spec/orm/activerecord_spec.rb +271 -0
  44. data/spec/orm/datamapper_spec.rb +161 -0
  45. data/spec/orm/sequel_spec.rb +192 -0
  46. data/spec/sanitized_file_spec.rb +612 -0
  47. data/spec/spec_helper.rb +99 -0
  48. data/spec/uploader/cache_spec.rb +196 -0
  49. data/spec/uploader/default_path_spec.rb +68 -0
  50. data/spec/uploader/extension_whitelist_spec.rb +44 -0
  51. data/spec/uploader/mountable_spec.rb +33 -0
  52. data/spec/uploader/paths_spec.rb +22 -0
  53. data/spec/uploader/processing_spec.rb +62 -0
  54. data/spec/uploader/proxy_spec.rb +54 -0
  55. data/spec/uploader/remove_spec.rb +70 -0
  56. data/spec/uploader/store_spec.rb +274 -0
  57. data/spec/uploader/url_spec.rb +87 -0
  58. data/spec/uploader/versions_spec.rb +306 -0
  59. metadata +127 -0
@@ -0,0 +1,4 @@
1
+ scope 'merb-gen' do
2
+ dir = File.join(File.dirname(__FILE__), 'lib', 'generators/')
3
+ Merb.add_generators dir + 'uploader_generator'
4
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Jonas Nicklas
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,314 @@
1
+ = CarrierWave
2
+
3
+ http://carrierwave.rubyforge.org
4
+
5
+ == Summary
6
+
7
+ This plugin for Merb and Rails provides a simple and extremely flexible way to
8
+ upload files.
9
+
10
+ == Description
11
+
12
+ * RDoc Documentation {available at Rubyforge}[http://carrierwave.rubyforge.org/].
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
+
17
+ == Getting Started
18
+
19
+ Install the latest stable release:
20
+
21
+ [sudo] gem install carrierwave
22
+
23
+ Or the cutting edge development version:
24
+
25
+ [sudo] gem install jnicklas-carrierwave --source http://gems.github.com
26
+
27
+ In Merb, add it as a dependency to your config/dependencies.rb:
28
+
29
+ dependency 'carrierwave'
30
+
31
+ In Rails, add it to your environment.rb:
32
+
33
+ config.gem "carrierwave"
34
+
35
+ == Quick Start
36
+
37
+ Start off by generating an uploader:
38
+
39
+ merb-gen uploader Avatar
40
+
41
+ or in Rails:
42
+
43
+ script/generate uploader Avatar
44
+
45
+ this should give you a file in:
46
+
47
+ app/uploaders/avatar_uploader.rb
48
+
49
+ Check out this file for some hints on how you can customize your uploader. It
50
+ should look something like this:
51
+
52
+ class AvatarUploader < CarrierWave::Uploader::Base
53
+ storage :file
54
+ end
55
+
56
+ You can use your uploader class to store and retrieve files like this:
57
+
58
+ uploader = AvatarUploader.new
59
+
60
+ uploader.store!(my_file)
61
+
62
+ uploader.retrieve_from_store!('my_file.png')
63
+
64
+ CarrierWave gives you a +store+ for permanent storage, and a +cache+ for
65
+ temporary storage. You can use different stores, at the moment a filesystem
66
+ store and an Amazon S3 store are bundled.
67
+
68
+ Most of the time you are going to want to use CarrierWave together with an ORM.
69
+ It is quite simple to mount uploaders on columns in your model, so you can
70
+ simply assign files and get going:
71
+
72
+ === ActiveRecord, DataMapper, Sequel
73
+
74
+ If you are *not* using Merb or Rails you'll need to require the relevant ORM
75
+ extension.
76
+
77
+ require 'carrierwave/orm/activerecord'
78
+ require 'carrierwave/orm/datamapper'
79
+ require 'carrierwave/orm/sequel'
80
+
81
+ Open your model file, for ActiveRecord do something like:
82
+
83
+ class User < ActiveRecord::Base
84
+ mount_uploader :avatar, AvatarUploader
85
+ end
86
+
87
+ Or for DataMapper:
88
+
89
+ class User
90
+ include DataMapper::Resource
91
+
92
+ mount_uploader :avatar, AvatarUploader
93
+ end
94
+
95
+ Or for Sequel
96
+
97
+ class User < Sequel::Model
98
+ mount_uploader :avatar, AvatarUploader
99
+ end
100
+
101
+ Now you can cache files by assigning them to the attribute, they will
102
+ automatically be stored when the record is saved.
103
+
104
+ u = User.new
105
+ u.avatar = params[:file]
106
+ u.avatar = File.open('somewhere')
107
+ u.save!
108
+ u.avatar.url # => '/url/to/file.png'
109
+ u.avatar.current_path # => 'path/to/file.png'
110
+
111
+ == Changing the storage directory
112
+
113
+ In order to change where uploaded files are put, just override the +store_dir+
114
+ method:
115
+
116
+ class MyUploader < CarrierWave::Uploader::Base
117
+ def store_dir
118
+ 'public/my/upload/directory'
119
+ end
120
+ end
121
+
122
+ This works for the file storage as well as Amazon S3.
123
+
124
+ == Adding versions
125
+
126
+ Often you'll want to add different versions of the same file. The classic
127
+ example is image thumbnails. There is built in support for this:
128
+
129
+ class MyUploader < CarrierWave::Uploader::Base
130
+ include CarrierWave::RMagick
131
+
132
+ process :resize => [800, 800]
133
+
134
+ version :thumb do
135
+ process :crop_resized => [200,200]
136
+ end
137
+
138
+ end
139
+
140
+ When this uploader is used, an uploaded image would be scaled to be no larger
141
+ than 800 by 800 pixels. A version called thumb is then created, which is scaled
142
+ and cropped to exactly 200 by 200 pixels. The uploader could be used like this:
143
+
144
+ uploader = AvatarUploader.new
145
+ uploader.store!(my_file) # size: 1024x768
146
+
147
+ uploader.url # => '/url/to/my_file.png' # size: 800x600
148
+ uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
149
+
150
+ One important thing to remember is that process is called *before* versions are
151
+ created. This can cut down on processing cost.
152
+
153
+ It is possible to nest versions within versions:
154
+
155
+ class MyUploader < CarrierWave::Uploader::Base
156
+
157
+ version :animal do
158
+ version :human
159
+ version :monkey
160
+ version :llama
161
+ end
162
+ end
163
+
164
+ == Making uploads work across form redisplays
165
+
166
+ Often you'll notice that uploaded files disappear when a validation fails.
167
+ CarrierWave has a feature that makes it easy to remember the uploaded file even
168
+ in that case. Suppose your +user+ model has an uploader mounted on +avatar+
169
+ file, just add a hidden field called +avatar_cache+. In Rails, this would look
170
+ like this:
171
+
172
+ <% form_for @user do |f| %>
173
+ <p>
174
+ <label>My Avatar</label>
175
+ <%= f.file_field :avatar %>
176
+ <%= f.hidden_field :avatar_cache %>
177
+ </p>
178
+ <% end %>
179
+
180
+ It might be a good idea to show th user that a file has been uploaded, in the
181
+ case of images, a small thumbnail would be a good indicator:
182
+
183
+ <% form_for @user do |f| %>
184
+ <p>
185
+ <label>My Avatar</label>
186
+ <%= image_tag(@user.avatar.url) if @user.avatar %>
187
+ <%= f.file_field :avatar %>
188
+ <%= f.hidden_field :avatar_cache %>
189
+ </p>
190
+ <% end %>
191
+
192
+ NOTE: this feature currently requires write access to your filesystem. If write
193
+ access is unavailable you will not be able to upload files. You can prevent
194
+ CarrierWave from writing to the file system by setting
195
+ `CarrierWave.config[:cache_to_cache_dir] = false`. This will however break
196
+ redisplays of forms.
197
+
198
+ == Providing a default path
199
+
200
+ In many cases, especially when working with images, it might be a good idea to
201
+ provide a default path, a fallback in case no file has been uploaded. You can do
202
+ this easily by overriding the +default_path+ method in your uploader:
203
+
204
+ class MyUploader < CarrierWave::Uploader::Base
205
+ def default_path
206
+ "images/fallback/" + [version_name, "default.png"].compact.join('_')
207
+ end
208
+ end
209
+
210
+ == Using Amazon S3
211
+
212
+ You'll need to configure a bucket, access id and secret key like this:
213
+
214
+ CarrierWave.config[:s3][:access_key_id] = 'xxxxxx'
215
+ CarrierWave.config[:s3][:secret_access_key] = 'xxxxxx'
216
+ CarrierWave.config[:s3][:bucket] = 'name_of_bucket'
217
+
218
+ Do this in an initializer in Rails, and in a +before_app_loads+ block in Merb.
219
+
220
+ And then in your uploader, set the storage to :s3
221
+
222
+ class AvatarUploader <
223
+ storage :s3
224
+ end
225
+
226
+ That's it! You can still use the +CarrierWave::Uploader#url+ method to return
227
+ the url to the file on Amazon S3
228
+
229
+ == Using RMagick
230
+
231
+ If you're uploading images, you'll probably want to manipulate them in some way,
232
+ you might want to create thumbnail images for example. CarrierWave comes with a
233
+ small library to make manipulating images with RMagick easier, you'll need to
234
+ include it in your Uploader:
235
+
236
+ class AvatarUploader < CarrierWave::Uploader::Base
237
+ include CarrierWave::RMagick
238
+ end
239
+
240
+ The RMagick module gives you a few methods, like
241
+ +CarrierWave::RMagick#crop_resized+ which manipulate the image file in some way.
242
+ You can set a +process+ callback, which will call that method any time a file is
243
+ uploaded.
244
+
245
+ class AvatarUploader < CarrierWave::Uploader::Base
246
+ include CarrierWave::RMagick
247
+
248
+ process :crop_resized => [200, 200]
249
+ process :convert => 'png'
250
+
251
+ def filename
252
+ super + '.png'
253
+ end
254
+ end
255
+
256
+ Check out the manipulate! method, which makes it easy for you to write your own
257
+ manipulation methods.
258
+
259
+ == Using ImageScience
260
+
261
+ ImageScience works the same way as RMagick.
262
+
263
+ class AvatarUploader < CarrierWave::Uploader::Base
264
+ include CarrierWave::ImageScience
265
+
266
+ process :crop_resized => [200, 200]
267
+ end
268
+
269
+ == Migrating
270
+
271
+ If you are using Paperclip, you can use the provided compatibility module:
272
+
273
+ class AvatarUploader < CarrierWave::Uploader::Base
274
+ include CarrierWave::Compatibility::Paperclip
275
+ end
276
+
277
+ See the documentation for +Paperclip::Compatibility::Paperclip+ for more
278
+ detaills.
279
+
280
+ Be sure to use mount_on to specify the correct column:
281
+
282
+ mount_uploader :avatar, AvatarUploader, :mount_on => :avatar_file_name
283
+
284
+ Unfortunately AttachmentFoo differs too much in philosophy for there to be a
285
+ sensible compatibility mode. Patches for migrating from other solutions will be
286
+ happily accepted.
287
+
288
+ == i18n
289
+
290
+ The activerecord validations use the Rails i18n framework. Add these keys to
291
+ your translations file:
292
+
293
+ carrierwave:
294
+ errors:
295
+ integrity: 'Not an image.'
296
+ processing: 'Cannot resize image.'
297
+
298
+ == Contributors
299
+
300
+ These people have contributed their time and effort to CarrierWave:
301
+
302
+ * Jonas Nicklas
303
+ * Pavel Kunc
304
+
305
+ == License
306
+
307
+ MIT-License, see the separate LICENSE file in the source distribution.
308
+
309
+ == Read the source
310
+
311
+ CarrierWave is still young, but most of it is pretty well documented. It is also
312
+ extensively specced, and there are cucumber features for some common use cases.
313
+ Just dig in and look at the source for more in-depth explanation of what things
314
+ are doing.
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/carrierwave'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ Hoe.plugin :cucumberfeatures
10
+
11
+ $hoe = Hoe.spec 'carrierwave' do
12
+ self.developer 'Jonas Nicklas', 'jonas.nicklas@gmail.com'
13
+ self.rubyforge_name = self.name
14
+ self.readme_file = 'README.rdoc'
15
+ self.version = CarrierWave::VERSION
16
+ self.extra_dev_deps << ['rspec', '>=1.2.8']
17
+ self.extra_dev_deps << ['cucumber', '>=0.3.96']
18
+ self.extra_dev_deps << ['activerecord', '>=2.3.3']
19
+ self.extra_dev_deps << ['dm-core', '>=0.9.11']
20
+ self.extra_dev_deps << ['sequel', '>=3.2.0']
21
+ self.extra_dev_deps << ['rmagick', '>=2.10.0']
22
+ self.extra_rdoc_files << 'README.rdoc'
23
+ self.extra_rdoc_files << 'LICENSE'
24
+ end
25
+
26
+ require 'newgem/tasks'
27
+ Dir['tasks/**/*.rake'].each { |t| load t }
28
+
29
+ task :default => [:spec, :features]
@@ -0,0 +1,140 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+ require 'carrierwave/core_ext/blank'
5
+ require 'carrierwave/core_ext/module_setup'
6
+ require 'carrierwave/core_ext/inheritable_attributes'
7
+
8
+ module CarrierWave
9
+
10
+ VERSION = "0.3.2"
11
+
12
+ class << self
13
+ attr_accessor :config, :logger
14
+
15
+ def logger
16
+ return @logger if @logger
17
+ require 'logger'
18
+ @logger = Logger.new(STDOUT)
19
+ end
20
+
21
+ ##
22
+ # Generates a unique cache id for use in the caching system
23
+ #
24
+ # === Returns
25
+ #
26
+ # [String] a cache id in the format YYYYMMDD-HHMM-PID-RND
27
+ #
28
+ def generate_cache_id
29
+ Time.now.strftime('%Y%m%d-%H%M') + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
30
+ end
31
+ end
32
+
33
+ class UploadError < StandardError; end
34
+ class NoFileError < UploadError; end
35
+ class FormNotMultipart < UploadError
36
+ def message
37
+ "You tried to assign a String or a Pathname to an uploader, for security reasons, this is not allowed.\n\n If this is a file upload, please check that your upload form is multipart encoded."
38
+ end
39
+ end
40
+ class IntegrityError < UploadError; end
41
+ class InvalidParameter < UploadError; end
42
+ # Should be used by methods used as process callbacks.
43
+ class ProcessingError < UploadError; end
44
+
45
+ autoload :SanitizedFile, 'carrierwave/sanitized_file'
46
+ autoload :Mount, 'carrierwave/mount'
47
+ autoload :RMagick, 'carrierwave/processing/rmagick'
48
+ autoload :ImageScience, 'carrierwave/processing/image_science'
49
+
50
+ module Storage
51
+ autoload :Abstract, 'carrierwave/storage/abstract'
52
+ autoload :File, 'carrierwave/storage/file'
53
+ autoload :S3, 'carrierwave/storage/s3'
54
+ end
55
+
56
+ module Uploader
57
+ autoload :Base, 'carrierwave/uploader'
58
+ autoload :Cache, 'carrierwave/uploader/cache'
59
+ autoload :Store, 'carrierwave/uploader/store'
60
+ autoload :Callbacks, 'carrierwave/uploader/callbacks'
61
+ autoload :Processing, 'carrierwave/uploader/processing'
62
+ autoload :Versions, 'carrierwave/uploader/versions'
63
+ autoload :Remove, 'carrierwave/uploader/remove'
64
+ autoload :Paths, 'carrierwave/uploader/paths'
65
+ autoload :ExtensionWhitelist, 'carrierwave/uploader/extension_whitelist'
66
+ autoload :DefaultPath, 'carrierwave/uploader/default_path'
67
+ autoload :Proxy, 'carrierwave/uploader/proxy'
68
+ autoload :Url, 'carrierwave/uploader/url'
69
+ autoload :Mountable, 'carrierwave/uploader/mountable'
70
+ end
71
+
72
+ module Compatibility
73
+ autoload :Paperclip, 'carrierwave/compatibility/paperclip'
74
+ end
75
+
76
+ module Test
77
+ autoload :Matchers, 'carrierwave/test/matchers'
78
+ end
79
+
80
+ end
81
+
82
+ CarrierWave.config = {
83
+ :permissions => 0644,
84
+ :storage => :file,
85
+ :use_cache => true,
86
+ :storage_engines => {
87
+ :file => "CarrierWave::Storage::File",
88
+ :s3 => "CarrierWave::Storage::S3"
89
+ },
90
+ :s3 => {
91
+ :access => :public_read
92
+ },
93
+ :store_dir => 'uploads',
94
+ :cache_dir => 'uploads/tmp',
95
+ :cache_to_cache_dir => true,
96
+ :mount => {
97
+ :ignore_integrity_errors => true,
98
+ :ignore_processing_errors => true,
99
+ :validate_integrity => true,
100
+ :validate_processing => true
101
+ }
102
+ }
103
+
104
+ if defined?(Merb::Plugins)
105
+ CarrierWave.config[:root] = Merb.root
106
+ CarrierWave.config[:public] = Merb.dir_for(:public)
107
+
108
+ Merb::BootLoader.before_app_loads do
109
+ # Set logger
110
+ CarrierWave.logger ||= Merb.logger
111
+ # Setup path for uploaders and load all of them before classes are loaded
112
+ Merb.push_path(:uploaders, Merb.root / 'app' / 'uploaders', '*.rb')
113
+ Dir.glob(File.join(Merb.load_paths[:uploaders])).each {|f| require f }
114
+ end
115
+
116
+ orm_path = File.dirname(__FILE__) / 'carrierwave' / 'orm' / Merb.orm
117
+ require orm_path if File.exist?(orm_path + '.rb')
118
+
119
+ Merb.add_generators File.dirname(__FILE__) / 'generators' / 'uploader_generator'
120
+
121
+ elsif defined?(Rails)
122
+ begin
123
+ CarrierWave.logger = Rails.logger
124
+ rescue
125
+ # Rails < 2.1
126
+ CarrierWave.logger = RAILS_DEFAULT_LOGGER
127
+ end
128
+ CarrierWave.config[:root] = Rails.root
129
+ CarrierWave.config[:public] = File.join(Rails.root, 'public')
130
+
131
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", 'activerecord')
132
+
133
+ ActiveSupport::Dependencies.load_paths << File.join(Rails.root, "app", "uploaders")
134
+
135
+ elsif defined?(Sinatra)
136
+
137
+ CarrierWave.config[:root] = Sinatra::Application.root
138
+ CarrierWave.config[:public] = Sinatra::Application.public
139
+
140
+ end