plowdawg-carrierwave 0.5.8

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 (36) hide show
  1. data/README.md +674 -0
  2. data/lib/carrierwave.rb +109 -0
  3. data/lib/carrierwave/compatibility/paperclip.rb +95 -0
  4. data/lib/carrierwave/locale/en.yml +5 -0
  5. data/lib/carrierwave/mount.rb +382 -0
  6. data/lib/carrierwave/orm/activerecord.rb +46 -0
  7. data/lib/carrierwave/processing/mime_types.rb +58 -0
  8. data/lib/carrierwave/processing/mini_magick.rb +253 -0
  9. data/lib/carrierwave/processing/rmagick.rb +279 -0
  10. data/lib/carrierwave/sanitized_file.rb +302 -0
  11. data/lib/carrierwave/storage/abstract.rb +30 -0
  12. data/lib/carrierwave/storage/cloud_files.rb +188 -0
  13. data/lib/carrierwave/storage/file.rb +47 -0
  14. data/lib/carrierwave/storage/fog.rb +332 -0
  15. data/lib/carrierwave/storage/right_s3.rb +1 -0
  16. data/lib/carrierwave/storage/s3.rb +240 -0
  17. data/lib/carrierwave/test/matchers.rb +164 -0
  18. data/lib/carrierwave/uploader.rb +44 -0
  19. data/lib/carrierwave/uploader/cache.rb +160 -0
  20. data/lib/carrierwave/uploader/callbacks.rb +35 -0
  21. data/lib/carrierwave/uploader/configuration.rb +162 -0
  22. data/lib/carrierwave/uploader/default_url.rb +19 -0
  23. data/lib/carrierwave/uploader/download.rb +75 -0
  24. data/lib/carrierwave/uploader/extension_whitelist.rb +49 -0
  25. data/lib/carrierwave/uploader/mountable.rb +39 -0
  26. data/lib/carrierwave/uploader/processing.rb +90 -0
  27. data/lib/carrierwave/uploader/proxy.rb +77 -0
  28. data/lib/carrierwave/uploader/remove.rb +23 -0
  29. data/lib/carrierwave/uploader/store.rb +113 -0
  30. data/lib/carrierwave/uploader/url.rb +45 -0
  31. data/lib/carrierwave/uploader/versions.rb +237 -0
  32. data/lib/carrierwave/validations/active_model.rb +79 -0
  33. data/lib/carrierwave/version.rb +3 -0
  34. data/lib/generators/templates/uploader.rb +49 -0
  35. data/lib/generators/uploader_generator.rb +7 -0
  36. metadata +215 -0
@@ -0,0 +1,109 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+ require 'active_support/core_ext/object/blank'
5
+ require 'active_support/core_ext/class/attribute'
6
+
7
+ begin
8
+ require 'active_support/core_ext/class/inheritable_attributes'
9
+ rescue LoadError
10
+ end
11
+
12
+ require 'active_support/concern'
13
+ require 'active_support/memoizable'
14
+
15
+ module CarrierWave
16
+
17
+ class << self
18
+ attr_accessor :root
19
+
20
+ def configure(&block)
21
+ CarrierWave::Uploader::Base.configure(&block)
22
+ end
23
+
24
+ def clean_cached_files!
25
+ CarrierWave::Uploader::Base.clean_cached_files!
26
+ end
27
+ end
28
+
29
+ class UploadError < StandardError; end
30
+ class IntegrityError < UploadError; end
31
+ class InvalidParameter < UploadError; end
32
+ class ProcessingError < UploadError; end
33
+ class DownloadError < UploadError; end
34
+
35
+ autoload :SanitizedFile, 'carrierwave/sanitized_file'
36
+ autoload :Mount, 'carrierwave/mount'
37
+ autoload :RMagick, 'carrierwave/processing/rmagick'
38
+ autoload :ImageScience, 'carrierwave/processing/image_science'
39
+ autoload :MiniMagick, 'carrierwave/processing/mini_magick'
40
+ autoload :MimeTypes, 'carrierwave/processing/mime_types'
41
+ autoload :VERSION, 'carrierwave/version'
42
+
43
+ module Storage
44
+ autoload :Abstract, 'carrierwave/storage/abstract'
45
+ autoload :File, 'carrierwave/storage/file'
46
+ autoload :Fog, 'carrierwave/storage/fog'
47
+ autoload :S3, 'carrierwave/storage/s3'
48
+ autoload :GridFS, 'carrierwave/storage/grid_fs'
49
+ autoload :RightS3, 'carrierwave/storage/right_s3'
50
+ autoload :CloudFiles, 'carrierwave/storage/cloud_files'
51
+ end
52
+
53
+ module Uploader
54
+ autoload :Base, 'carrierwave/uploader'
55
+ autoload :Cache, 'carrierwave/uploader/cache'
56
+ autoload :Store, 'carrierwave/uploader/store'
57
+ autoload :Download, 'carrierwave/uploader/download'
58
+ autoload :Callbacks, 'carrierwave/uploader/callbacks'
59
+ autoload :Processing, 'carrierwave/uploader/processing'
60
+ autoload :Versions, 'carrierwave/uploader/versions'
61
+ autoload :Remove, 'carrierwave/uploader/remove'
62
+ autoload :ExtensionWhitelist, 'carrierwave/uploader/extension_whitelist'
63
+ autoload :DefaultUrl, 'carrierwave/uploader/default_url'
64
+ autoload :Proxy, 'carrierwave/uploader/proxy'
65
+ autoload :Url, 'carrierwave/uploader/url'
66
+ autoload :Mountable, 'carrierwave/uploader/mountable'
67
+ autoload :Configuration, 'carrierwave/uploader/configuration'
68
+ end
69
+
70
+ module Compatibility
71
+ autoload :Paperclip, 'carrierwave/compatibility/paperclip'
72
+ end
73
+
74
+ module Test
75
+ autoload :Matchers, 'carrierwave/test/matchers'
76
+ end
77
+
78
+ end
79
+
80
+ if defined?(Merb)
81
+
82
+ CarrierWave.root = Merb.dir_for(:public)
83
+ Merb::BootLoader.before_app_loads do
84
+ # Setup path for uploaders and load all of them before classes are loaded
85
+ Merb.push_path(:uploaders, Merb.root / 'app' / 'uploaders', '*.rb')
86
+ Dir.glob(File.join(Merb.load_paths[:uploaders])).each {|f| require f }
87
+ end
88
+
89
+ elsif defined?(Rails)
90
+
91
+ module CarrierWave
92
+ class Railtie < Rails::Railtie
93
+ initializer "carrierwave.setup_paths" do
94
+ CarrierWave.root = Rails.root.join(Rails.public_path).to_s
95
+ end
96
+
97
+ initializer "carrierwave.active_record" do
98
+ ActiveSupport.on_load :active_record do
99
+ require 'carrierwave/orm/activerecord'
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ elsif defined?(Sinatra)
106
+
107
+ CarrierWave.root = Sinatra::Application.public
108
+
109
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Compatibility
5
+
6
+ ##
7
+ # Mix this module into an Uploader to make it mimic Paperclip's storage paths
8
+ # This will make your Uploader use the same default storage path as paperclip
9
+ # does. If you need to override it, you can override the +paperclip_path+ method
10
+ # and provide a Paperclip style path:
11
+ #
12
+ # class MyUploader < CarrierWave::Uploader::Base
13
+ # include CarrierWave::Compatibility::Paperclip
14
+ #
15
+ # def paperclip_path
16
+ # ":rails_root/public/uploads/:id/:attachment/:style_:basename.:extension"
17
+ # end
18
+ # end
19
+ #
20
+ # ---
21
+ #
22
+ # This file contains code taken from Paperclip
23
+ #
24
+ # LICENSE
25
+ #
26
+ # The MIT License
27
+ #
28
+ # Copyright (c) 2008 Jon Yurek and thoughtbot, inc.
29
+ #
30
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
31
+ # of this software and associated documentation files (the "Software"), to deal
32
+ # in the Software without restriction, including without limitation the rights
33
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34
+ # copies of the Software, and to permit persons to whom the Software is
35
+ # furnished to do so, subject to the following conditions:
36
+ #
37
+ # The above copyright notice and this permission notice shall be included in
38
+ # all copies or substantial portions of the Software.
39
+ #
40
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
45
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
46
+ # THE SOFTWARE.
47
+ #
48
+ module Paperclip
49
+
50
+ def store_path(for_file=filename)
51
+ path = paperclip_path
52
+ path ||= File.join(*[store_dir, paperclip_style.to_s, for_file].compact)
53
+ interpolate_paperclip_path(path, for_file)
54
+ end
55
+
56
+ def store_dir
57
+ ":rails_root/public/system/:attachment/:id"
58
+ end
59
+
60
+ def paperclip_default_style
61
+ :original
62
+ end
63
+
64
+ def paperclip_path
65
+ end
66
+
67
+ def paperclip_style
68
+ version_name || paperclip_default_style
69
+ end
70
+
71
+ private
72
+
73
+ def interpolate_paperclip_path(path, filename)
74
+ mappings.inject(path) do |agg, pair|
75
+ agg.gsub(":#{pair[0]}") { pair[1].call(self, filename).to_s }
76
+ end
77
+ end
78
+
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_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
+ end
92
+
93
+ end # Paperclip
94
+ end # Compatibility
95
+ end # CarrierWave
@@ -0,0 +1,5 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ carrierwave_processing_error: failed to be processed
5
+ carrierwave_integrity_error: is not an allowed file type
@@ -0,0 +1,382 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+
5
+ ##
6
+ # If a Class is extended with this module, it gains the mount_uploader
7
+ # method, which is used for mapping attributes to uploaders and allowing
8
+ # easy assignment.
9
+ #
10
+ # You can use mount_uploader with pretty much any class, however it is
11
+ # intended to be used with some kind of persistent storage, like an ORM.
12
+ # If you want to persist the uploaded files in a particular Class, it
13
+ # needs to implement a `read_uploader` and a `write_uploader` method.
14
+ #
15
+ module Mount
16
+
17
+ ##
18
+ # === Returns
19
+ #
20
+ # [Hash{Symbol => CarrierWave}] what uploaders are mounted on which columns
21
+ #
22
+ def uploaders
23
+ @uploaders ||= {}
24
+ @uploaders = superclass.uploaders.merge(@uploaders) if superclass.respond_to?(:uploaders)
25
+ @uploaders
26
+ end
27
+
28
+ def uploader_options
29
+ @uploader_options ||= {}
30
+ @uploader_options = superclass.uploader_options.merge(@uploader_options) if superclass.respond_to?(:uploader_options)
31
+ @uploader_options
32
+ end
33
+
34
+ ##
35
+ # Return a particular option for a particular uploader
36
+ #
37
+ # === Parameters
38
+ #
39
+ # [column (Symbol)] The column the uploader is mounted at
40
+ # [option (Symbol)] The option, e.g. validate_integrity
41
+ #
42
+ # === Returns
43
+ #
44
+ # [Object] The option value
45
+ #
46
+ def uploader_option(column, option)
47
+ if uploader_options[column].has_key?(option)
48
+ uploader_options[column][option]
49
+ else
50
+ uploaders[column].send(option)
51
+ end
52
+ end
53
+
54
+ ##
55
+ # Mounts the given uploader on the given column. This means that assigning
56
+ # and reading from the column will upload and retrieve files. Supposing
57
+ # that a User class has an uploader mounted on image, you can assign and
58
+ # retrieve files like this:
59
+ #
60
+ # @user.image # => <Uploader>
61
+ # @user.image.store!(some_file_object)
62
+ #
63
+ # @user.image.url # => '/some_url.png'
64
+ #
65
+ # It is also possible (but not recommended) to ommit the uploader, which
66
+ # will create an anonymous uploader class.
67
+ #
68
+ # Passing a block makes it possible to customize the uploader. This can be
69
+ # convenient for brevity, but if there is any significatnt logic in the
70
+ # uploader, you should do the right thing and have it in its own file.
71
+ #
72
+ # === Added instance methods
73
+ #
74
+ # Supposing a class has used +mount_uploader+ to mount an uploader on a column
75
+ # named +image+, in that case the following methods will be added to the class:
76
+ #
77
+ # [image] Returns an instance of the uploader only if anything has been uploaded
78
+ # [image=] Caches the given file
79
+ #
80
+ # [image_url] Returns the url to the uploaded file
81
+ #
82
+ # [image_cache] Returns a string that identifies the cache location of the file
83
+ # [image_cache=] Retrieves the file from the cache based on the given cache name
84
+ #
85
+ # [remote_image_url] Returns previously cached remote url
86
+ # [remote_image_url=] Retrieve the file from the remote url
87
+ #
88
+ # [remove_image] An attribute reader that can be used with a checkbox to mark a file for removal
89
+ # [remove_image=] An attribute writer that can be used with a checkbox to mark a file for removal
90
+ # [remove_image?] Whether the file should be removed when store_image! is called.
91
+ #
92
+ # [store_image!] Stores a file that has been assigned with +image=+
93
+ # [remove_image!] Removes the uploaded file from the filesystem.
94
+ #
95
+ # [image_integrity_error] Returns an error object if the last file to be assigned caused an integrity error
96
+ # [image_processing_error] Returns an error object if the last file to be assigned caused a processing error
97
+ #
98
+ # [write_image_identifier] Uses the write_uploader method to set the identifier.
99
+ # [image_identifier] Reads out the identifier of the file
100
+ #
101
+ # === Parameters
102
+ #
103
+ # [column (Symbol)] the attribute to mount this uploader on
104
+ # [uploader (CarrierWave::Uploader)] the uploader class to mount
105
+ # [options (Hash{Symbol => Object})] a set of options
106
+ # [&block (Proc)] customize anonymous uploaders
107
+ #
108
+ # === Options
109
+ #
110
+ # [:mount_on => Symbol] if the name of the column to be serialized to differs you can override it using this option
111
+ # [:ignore_integrity_errors => Boolean] if set to true, integrity errors will result in caching failing silently
112
+ # [:ignore_processing_errors => Boolean] if set to true, processing errors will result in caching failing silently
113
+ #
114
+ # === Examples
115
+ #
116
+ # Mounting uploaders on different columns.
117
+ #
118
+ # class Song
119
+ # mount_uploader :lyrics, LyricsUploader
120
+ # mount_uploader :alternative_lyrics, LyricsUploader
121
+ # mount_uploader :file, SongUploader
122
+ # end
123
+ #
124
+ # This will add an anonymous uploader with only the default settings:
125
+ #
126
+ # class Data
127
+ # mount_uploader :csv
128
+ # end
129
+ #
130
+ # this will add an anonymous uploader overriding the store_dir:
131
+ #
132
+ # class Product
133
+ # mount_uploader :blueprint do
134
+ # def store_dir
135
+ # 'blueprints'
136
+ # end
137
+ # end
138
+ # end
139
+ #
140
+ def mount_uploader(column, uploader=nil, options={}, &block)
141
+ if block_given?
142
+ uploader = Class.new(uploader || CarrierWave::Uploader::Base)
143
+ uploader.class_eval(&block)
144
+ uploader.recursively_apply_block_to_versions(&block)
145
+ else
146
+ uploader ||= Class.new(CarrierWave::Uploader::Base)
147
+ end
148
+
149
+ uploaders[column.to_sym] = uploader
150
+ uploader_options[column.to_sym] = options
151
+
152
+ include CarrierWave::Mount::Extension
153
+
154
+ # Make sure to write over accessors directly defined on the class.
155
+ # Simply super to the included module below.
156
+ class_eval <<-RUBY, __FILE__, __LINE__+1
157
+ def #{column}; super; end
158
+ def #{column}=(new_file); super; end
159
+ RUBY
160
+
161
+ # Mixing this in as a Module instead of class_evaling directly, so we
162
+ # can maintain the ability to super to any of these methods from within
163
+ # the class.
164
+ mod = Module.new
165
+ include mod
166
+ mod.class_eval <<-RUBY, __FILE__, __LINE__+1
167
+
168
+ def #{column}
169
+ _mounter(:#{column}).uploader
170
+ end
171
+
172
+ def #{column}=(new_file)
173
+ _mounter(:#{column}).cache(new_file)
174
+ end
175
+
176
+ def #{column}?
177
+ !_mounter(:#{column}).blank?
178
+ end
179
+
180
+ def #{column}_url(*args)
181
+ _mounter(:#{column}).url(*args)
182
+ end
183
+
184
+ def #{column}_cache
185
+ _mounter(:#{column}).cache_name
186
+ end
187
+
188
+ def #{column}_cache=(cache_name)
189
+ _mounter(:#{column}).cache_name = cache_name
190
+ end
191
+
192
+ def remote_#{column}_url
193
+ _mounter(:#{column}).remote_url
194
+ end
195
+
196
+ def remote_#{column}_url=(url)
197
+ _mounter(:#{column}).remote_url = url
198
+ end
199
+
200
+ def remove_#{column}
201
+ _mounter(:#{column}).remove
202
+ end
203
+
204
+ def remove_#{column}!
205
+ _mounter(:#{column}).remove!
206
+ end
207
+
208
+ def remove_#{column}=(value)
209
+ _mounter(:#{column}).remove = value
210
+ end
211
+
212
+ def remove_#{column}?
213
+ _mounter(:#{column}).remove?
214
+ end
215
+
216
+ def store_#{column}!
217
+ _mounter(:#{column}).store!
218
+ end
219
+
220
+ def #{column}_integrity_error
221
+ _mounter(:#{column}).integrity_error
222
+ end
223
+
224
+ def #{column}_processing_error
225
+ _mounter(:#{column}).processing_error
226
+ end
227
+
228
+ def write_#{column}_identifier
229
+ _mounter(:#{column}).write_identifier
230
+ end
231
+
232
+ def #{column}_identifier
233
+ _mounter(:#{column}).identifier
234
+ end
235
+
236
+ def store_previous_model_for_#{column}
237
+ serialization_column = _mounter(:#{column}).serialization_column
238
+
239
+ if #{column}.remove_previously_stored_files_after_update && send(:"\#{serialization_column}_changed?")
240
+ @previous_model_for_#{column} ||= self.find_previous_model_for_#{column}
241
+ end
242
+ end
243
+
244
+ def find_previous_model_for_#{column}
245
+ self.class.find(to_key.first)
246
+ end
247
+
248
+ def remove_previously_stored_#{column}
249
+ if @previous_model_for_#{column} && @previous_model_for_#{column}.#{column}.path != #{column}.path
250
+ @previous_model_for_#{column}.#{column}.remove!
251
+ @previous_model_for_#{column} = nil
252
+ end
253
+ end
254
+
255
+ RUBY
256
+ end
257
+
258
+ module Extension
259
+
260
+ ##
261
+ # overwrite this to read from a serialized attribute
262
+ #
263
+ def read_uploader(column); end
264
+
265
+ ##
266
+ # overwrite this to write to a serialized attribute
267
+ #
268
+ def write_uploader(column, identifier); end
269
+
270
+ private
271
+
272
+ def _mounter(column)
273
+ # We cannot memoize in frozen objects :(
274
+ return Mounter.new(self, column) if frozen?
275
+ @_mounters ||= {}
276
+ @_mounters[column] ||= Mounter.new(self, column)
277
+ end
278
+
279
+ end # Extension
280
+
281
+ # this is an internal class, used by CarrierWave::Mount so that
282
+ # we don't pollute the model with a lot of methods.
283
+ class Mounter #:nodoc:
284
+ extend ActiveSupport::Memoizable
285
+
286
+ attr_reader :column, :record, :remote_url, :integrity_error, :processing_error
287
+ attr_accessor :remove
288
+
289
+ def initialize(record, column, options={})
290
+ @record = record
291
+ @column = column
292
+ @options = record.class.uploader_options[column]
293
+ end
294
+
295
+ def write_identifier
296
+ if remove?
297
+ record.write_uploader(serialization_column, '')
298
+ elsif not uploader.identifier.blank?
299
+ record.write_uploader(serialization_column, uploader.identifier)
300
+ end
301
+ end
302
+
303
+ def identifier
304
+ record.read_uploader(serialization_column)
305
+ end
306
+
307
+ def uploader
308
+ @uploader ||= record.class.uploaders[column].new(record, column)
309
+
310
+ if @uploader.blank? and not identifier.blank?
311
+ @uploader.retrieve_from_store!(identifier)
312
+ end
313
+ return @uploader
314
+ end
315
+
316
+ def cache(new_file)
317
+ uploader.cache!(new_file)
318
+ @integrity_error = nil
319
+ @processing_error = nil
320
+ rescue CarrierWave::IntegrityError => e
321
+ @integrity_error = e
322
+ raise e unless option(:ignore_integrity_errors)
323
+ rescue CarrierWave::ProcessingError => e
324
+ @processing_error = e
325
+ raise e unless option(:ignore_processing_errors)
326
+ end
327
+
328
+ def cache_name
329
+ uploader.cache_name
330
+ end
331
+
332
+ def cache_name=(cache_name)
333
+ uploader.retrieve_from_cache!(cache_name) unless uploader.cached?
334
+ rescue CarrierWave::InvalidParameter
335
+ end
336
+
337
+ def remote_url=(url)
338
+ @remote_url = url
339
+ uploader.download!(url)
340
+ end
341
+
342
+ def store!
343
+ unless uploader.blank?
344
+ if remove?
345
+ uploader.remove!
346
+ else
347
+ uploader.store!
348
+ end
349
+ end
350
+ end
351
+
352
+ def url(*args)
353
+ uploader.url(*args)
354
+ end
355
+
356
+ def blank?
357
+ uploader.blank?
358
+ end
359
+
360
+ def remove?
361
+ !remove.blank? and remove !~ /\A0|false$\z/
362
+ end
363
+
364
+ def remove!
365
+ uploader.remove!
366
+ end
367
+
368
+ def serialization_column
369
+ option(:mount_on) || column
370
+ end
371
+
372
+ private
373
+
374
+ def option(name)
375
+ record.class.uploader_option(column, name)
376
+ end
377
+ memoize :option
378
+
379
+ end # Mounter
380
+
381
+ end # Mount
382
+ end # CarrierWave