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,164 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Test
5
+
6
+ ##
7
+ # These are some matchers that can be used in RSpec specs, to simplify the testing
8
+ # of uploaders.
9
+ #
10
+ module Matchers
11
+
12
+ class BeIdenticalTo # :nodoc:
13
+ def initialize(expected)
14
+ @expected = expected
15
+ end
16
+ def matches?(actual)
17
+ @actual = actual
18
+ FileUtils.identical?(@actual, @expected)
19
+ end
20
+ def failure_message
21
+ "expected #{@actual.inspect} to be identical to #{@expected.inspect}"
22
+ end
23
+ def negative_failure_message
24
+ "expected #{@actual.inspect} to not be identical to #{@expected.inspect}"
25
+ end
26
+ end
27
+
28
+ def be_identical_to(expected)
29
+ BeIdenticalTo.new(expected)
30
+ end
31
+
32
+ class HavePermissions # :nodoc:
33
+ def initialize(expected)
34
+ @expected = expected
35
+ end
36
+
37
+ def matches?(actual)
38
+ @actual = actual
39
+ # Satisfy expectation here. Return false or raise an error if it's not met.
40
+ (File.stat(@actual.path).mode & 0777) == @expected
41
+ end
42
+
43
+ def failure_message
44
+ "expected #{@actual.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
45
+ end
46
+
47
+ def negative_failure_message
48
+ "expected #{@actual.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
49
+ end
50
+ end
51
+
52
+ def have_permissions(expected)
53
+ HavePermissions.new(expected)
54
+ end
55
+
56
+ class BeNoLargerThan # :nodoc:
57
+ def initialize(width, height)
58
+ @width, @height = width, height
59
+ end
60
+
61
+ def matches?(actual)
62
+ @actual = actual
63
+ # Satisfy expectation here. Return false or raise an error if it's not met.
64
+ image = ImageLoader.load_image(@actual.current_path)
65
+ @actual_width = image.width
66
+ @actual_height = image.height
67
+ @actual_width <= @width && @actual_height <= @height
68
+ end
69
+
70
+ def failure_message
71
+ "expected #{@actual.current_path.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
72
+ end
73
+
74
+ def negative_failure_message
75
+ "expected #{@actual.current_path.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
76
+ end
77
+
78
+ end
79
+
80
+ def be_no_larger_than(width, height)
81
+ BeNoLargerThan.new(width, height)
82
+ end
83
+
84
+ class HaveDimensions # :nodoc:
85
+ def initialize(width, height)
86
+ @width, @height = width, height
87
+ end
88
+
89
+ def matches?(actual)
90
+ @actual = actual
91
+ # Satisfy expectation here. Return false or raise an error if it's not met.
92
+ image = ImageLoader.load_image(@actual.current_path)
93
+ @actual_width = image.width
94
+ @actual_height = image.height
95
+ @actual_width == @width && @actual_height == @height
96
+ end
97
+
98
+ def failure_message
99
+ "expected #{@actual.current_path.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
100
+ end
101
+
102
+ def negative_failure_message
103
+ "expected #{@actual.current_path.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
104
+ end
105
+
106
+ end
107
+
108
+ def have_dimensions(width, height)
109
+ HaveDimensions.new(width, height)
110
+ end
111
+
112
+ class ImageLoader # :nodoc:
113
+ def self.load_image(filename)
114
+ if defined? ::MiniMagick
115
+ MiniMagickWrapper.new(filename)
116
+ else
117
+ unless defined? ::Magick
118
+ begin
119
+ require 'rmagick'
120
+ rescue LoadError
121
+ require 'RMagick'
122
+ rescue LoadError
123
+ puts "WARNING: Failed to require rmagick, image processing may fail!"
124
+ end
125
+ end
126
+ MagickWrapper.new(filename)
127
+ end
128
+ end
129
+ end
130
+
131
+ class MagickWrapper # :nodoc:
132
+ attr_reader :image
133
+ def width
134
+ image.columns
135
+ end
136
+
137
+ def height
138
+ image.rows
139
+ end
140
+
141
+ def initialize(filename)
142
+ @image = ::Magick::Image.read(filename).first
143
+ end
144
+ end
145
+
146
+ class MiniMagickWrapper # :nodoc:
147
+ attr_reader :image
148
+ def width
149
+ image[:width]
150
+ end
151
+
152
+ def height
153
+ image[:height]
154
+ end
155
+
156
+ def initialize(filename)
157
+ @image = ::MiniMagick::Image.open(filename)
158
+ end
159
+ end
160
+
161
+ end # Matchers
162
+ end # Test
163
+ end # CarrierWave
164
+
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+
5
+ ##
6
+ # See CarrierWave::Uploader::Base
7
+ #
8
+ module Uploader
9
+
10
+ ##
11
+ # An uploader is a class that allows you to easily handle the caching and storage of
12
+ # uploaded files. Please refer to the README for configuration options.
13
+ #
14
+ # Once you have an uploader you can use it in isolation:
15
+ #
16
+ # my_uploader = MyUploader.new
17
+ # my_uploader.cache!(File.open(path_to_file))
18
+ # my_uploader.retrieve_from_store!('monkey.png')
19
+ #
20
+ # Alternatively, you can mount it on an ORM or other persistence layer, with
21
+ # +CarrierWave::Mount#mount_uploader+. There are extensions for activerecord and datamapper
22
+ # these are *very* simple (they are only a dozen lines of code), so adding your own should
23
+ # be trivial.
24
+ #
25
+ class Base
26
+ attr_reader :file
27
+
28
+ include CarrierWave::Uploader::Callbacks
29
+ include CarrierWave::Uploader::Proxy
30
+ include CarrierWave::Uploader::Url
31
+ include CarrierWave::Uploader::Mountable
32
+ include CarrierWave::Uploader::Cache
33
+ include CarrierWave::Uploader::Store
34
+ include CarrierWave::Uploader::Download
35
+ include CarrierWave::Uploader::Remove
36
+ include CarrierWave::Uploader::ExtensionWhitelist
37
+ include CarrierWave::Uploader::Processing
38
+ include CarrierWave::Uploader::Versions
39
+ include CarrierWave::Uploader::DefaultUrl
40
+ include CarrierWave::Uploader::Configuration
41
+ end # Base
42
+
43
+ end # Uploader
44
+ end # CarrierWave
@@ -0,0 +1,160 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+
5
+ class FormNotMultipart < UploadError
6
+ def message
7
+ "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."
8
+ end
9
+ end
10
+
11
+ ##
12
+ # Generates a unique cache id for use in the caching system
13
+ #
14
+ # === Returns
15
+ #
16
+ # [String] a cache id in the format YYYYMMDD-HHMM-PID-RND
17
+ #
18
+ def self.generate_cache_id
19
+ Time.now.strftime('%Y%m%d-%H%M') + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
20
+ end
21
+
22
+ module Uploader
23
+ module Cache
24
+ extend ActiveSupport::Concern
25
+
26
+ include CarrierWave::Uploader::Callbacks
27
+ include CarrierWave::Uploader::Configuration
28
+
29
+ module ClassMethods
30
+
31
+ ##
32
+ # Removes cached files which are older than one day. You could call this method
33
+ # from a rake task to clean out old cached files.
34
+ #
35
+ # You can call this method directly on the module like this:
36
+ #
37
+ # CarrierWave.clean_cached_files!
38
+ #
39
+ # === Note
40
+ #
41
+ # This only works as long as you haven't done anything funky with your cache_dir.
42
+ # It's recommended that you keep cache files in one place only.
43
+ #
44
+ def clean_cached_files!(seconds=60*60*24)
45
+ Dir.glob(File.expand_path(File.join(cache_dir, '*'), CarrierWave.root)).each do |dir|
46
+ time = dir.scan(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/).first.map { |t| t.to_i }
47
+ time = Time.utc(*time)
48
+ if time < (Time.now.utc - seconds)
49
+ FileUtils.rm_rf(dir)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ ##
56
+ # Returns true if the uploader has been cached
57
+ #
58
+ # === Returns
59
+ #
60
+ # [Bool] whether the current file is cached
61
+ #
62
+ def cached?
63
+ @cache_id
64
+ end
65
+
66
+ ##
67
+ # Caches the remotely stored file
68
+ #
69
+ # This is useful when about to process images. Most processing solutions
70
+ # require the file to be stored on the local filesystem.
71
+ #
72
+ def cache_stored_file!
73
+ sanitized = SanitizedFile.new :tempfile => StringIO.new(file.read),
74
+ :filename => File.basename(path), :content_type => file.content_type
75
+
76
+ cache! sanitized
77
+ end
78
+
79
+ ##
80
+ # Returns a String which uniquely identifies the currently cached file for later retrieval
81
+ #
82
+ # === Returns
83
+ #
84
+ # [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
85
+ #
86
+ def cache_name
87
+ File.join(cache_id, full_original_filename) if cache_id and original_filename
88
+ end
89
+
90
+ ##
91
+ # Caches the given file. Calls process! to trigger any process callbacks.
92
+ #
93
+ # === Parameters
94
+ #
95
+ # [new_file (File, IOString, Tempfile)] any kind of file object
96
+ #
97
+ # === Raises
98
+ #
99
+ # [CarrierWave::FormNotMultipart] if the assigned parameter is a string
100
+ #
101
+ def cache!(new_file)
102
+ new_file = CarrierWave::SanitizedFile.new(new_file)
103
+
104
+ unless new_file.empty?
105
+ raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
106
+
107
+ with_callbacks(:cache, new_file) do
108
+ self.cache_id = CarrierWave.generate_cache_id unless cache_id
109
+
110
+ @filename = new_file.filename
111
+ self.original_filename = new_file.filename
112
+
113
+ @file = new_file.copy_to(cache_path, permissions)
114
+ end
115
+ end
116
+ end
117
+
118
+ ##
119
+ # Retrieves the file with the given cache_name from the cache.
120
+ #
121
+ # === Parameters
122
+ #
123
+ # [cache_name (String)] uniquely identifies a cache file
124
+ #
125
+ # === Raises
126
+ #
127
+ # [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
128
+ #
129
+ def retrieve_from_cache!(cache_name)
130
+ with_callbacks(:retrieve_from_cache, cache_name) do
131
+ self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
132
+ @filename = original_filename
133
+ @file = CarrierWave::SanitizedFile.new(cache_path)
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ def cache_path
140
+ File.expand_path(File.join(cache_dir, cache_name), root)
141
+ end
142
+
143
+ attr_reader :cache_id, :original_filename
144
+
145
+ # We can override the full_original_filename method in other modules
146
+ alias_method :full_original_filename, :original_filename
147
+
148
+ def cache_id=(cache_id)
149
+ raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]{8}\-[\d]{4}\-[\d]+\-[\d]{4}\z/
150
+ @cache_id = cache_id
151
+ end
152
+
153
+ def original_filename=(filename)
154
+ raise CarrierWave::InvalidParameter, "invalid filename" if filename =~ CarrierWave::SanitizedFile.sanitize_regexp
155
+ @original_filename = filename
156
+ end
157
+
158
+ end # Cache
159
+ end # Uploader
160
+ end # CarrierWave
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Uploader
5
+ module Callbacks
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_attribute :_before_callbacks, :_after_callbacks,
10
+ :instance_writer => false
11
+ self._before_callbacks = Hash.new []
12
+ self._after_callbacks = Hash.new []
13
+ end
14
+
15
+ def with_callbacks(kind, *args)
16
+ self.class._before_callbacks[kind].each { |c| send c, *args }
17
+ yield
18
+ self.class._after_callbacks[kind].each { |c| send c, *args }
19
+ end
20
+
21
+ module ClassMethods
22
+ def before(kind, callback)
23
+ self._before_callbacks = self._before_callbacks.
24
+ merge kind => _before_callbacks[kind] + [callback]
25
+ end
26
+
27
+ def after(kind, callback)
28
+ self._after_callbacks = self._after_callbacks.
29
+ merge kind => _after_callbacks[kind] + [callback]
30
+ end
31
+ end # ClassMethods
32
+
33
+ end # Callbacks
34
+ end # Uploader
35
+ end # CarrierWave
@@ -0,0 +1,162 @@
1
+ module CarrierWave
2
+
3
+ module Uploader
4
+ module Configuration
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :_storage, :instance_writer => false
9
+
10
+ add_config :root
11
+ add_config :permissions
12
+ add_config :storage_engines
13
+ add_config :s3_access_policy
14
+ add_config :s3_bucket
15
+ add_config :s3_access_key_id
16
+ add_config :s3_secret_access_key
17
+ add_config :s3_cnamed
18
+ add_config :s3_headers
19
+ add_config :s3_region
20
+ add_config :s3_use_ssl
21
+ add_config :s3_authentication_timeout
22
+ add_config :cloud_files_username
23
+ add_config :cloud_files_api_key
24
+ add_config :cloud_files_container
25
+ add_config :cloud_files_cdn_host
26
+ add_config :cloud_files_auth_url
27
+ add_config :cloud_files_snet
28
+ add_config :grid_fs_connection
29
+ add_config :grid_fs_database
30
+ add_config :grid_fs_host
31
+ add_config :grid_fs_port
32
+ add_config :grid_fs_username
33
+ add_config :grid_fs_password
34
+ add_config :grid_fs_access_url
35
+ add_config :store_dir
36
+ add_config :cache_dir
37
+ add_config :enable_processing
38
+ add_config :ensure_multipart_form
39
+ add_config :delete_tmp_file_after_storage
40
+ add_config :remove_previously_stored_files_after_update
41
+
42
+ # fog
43
+ add_config :fog_attributes
44
+ add_config :fog_credentials
45
+ add_config :fog_directory
46
+ add_config :fog_host
47
+ add_config :fog_public
48
+ add_config :fog_authenticated_url_expiration
49
+
50
+ # Mounting
51
+ add_config :ignore_integrity_errors
52
+ add_config :ignore_processing_errors
53
+ add_config :validate_integrity
54
+ add_config :validate_processing
55
+ add_config :mount_on
56
+
57
+ # set default values
58
+ reset_config
59
+ end
60
+
61
+ module ClassMethods
62
+
63
+ ##
64
+ # Sets the storage engine to be used when storing files with this uploader.
65
+ # Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
66
+ # method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
67
+ # be added to CarrierWave::Uploader::Base.storage_engines so they can be referred
68
+ # to by a symbol, which should be more convenient
69
+ #
70
+ # If no argument is given, it will simply return the currently used storage engine.
71
+ #
72
+ # === Parameters
73
+ #
74
+ # [storage (Symbol, Class)] The storage engine to use for this uploader
75
+ #
76
+ # === Returns
77
+ #
78
+ # [Class] the storage engine to be used with this uploader
79
+ #
80
+ # === Examples
81
+ #
82
+ # storage :file
83
+ # storage CarrierWave::Storage::File
84
+ # storage MyCustomStorageEngine
85
+ #
86
+ def storage(storage = nil)
87
+ if storage
88
+ self._storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
89
+ end
90
+ _storage
91
+ end
92
+ alias_method :storage=, :storage
93
+
94
+ def add_config(name)
95
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
96
+ def self.#{name}(value=nil)
97
+ @#{name} = value if value
98
+ return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
99
+ name = superclass.#{name}
100
+ return nil if name.nil? && !instance_variable_defined?("@#{name}")
101
+ @#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
102
+ end
103
+
104
+ def self.#{name}=(value)
105
+ @#{name} = value
106
+ end
107
+
108
+ def #{name}
109
+ self.class.#{name}
110
+ end
111
+ RUBY
112
+ end
113
+
114
+ def configure
115
+ yield self
116
+ end
117
+
118
+ ##
119
+ # sets configuration back to default
120
+ #
121
+ def reset_config
122
+ configure do |config|
123
+ config.permissions = 0644
124
+ config.storage_engines = {
125
+ :file => "CarrierWave::Storage::File",
126
+ :fog => "CarrierWave::Storage::Fog",
127
+ :s3 => "CarrierWave::Storage::S3",
128
+ :grid_fs => "CarrierWave::Storage::GridFS",
129
+ :right_s3 => "CarrierWave::Storage::RightS3",
130
+ :cloud_files => "CarrierWave::Storage::CloudFiles"
131
+ }
132
+ config.storage = :file
133
+ config.s3_headers = {}
134
+ config.s3_access_policy = :public_read
135
+ config.s3_region = 'us-east-1'
136
+ config.s3_authentication_timeout = 600
137
+ config.grid_fs_database = 'carrierwave'
138
+ config.grid_fs_host = 'localhost'
139
+ config.grid_fs_port = 27017
140
+ config.fog_attributes = {}
141
+ config.fog_credentials = {}
142
+ config.fog_public = true
143
+ config.fog_authenticated_url_expiration = 600
144
+ config.store_dir = 'uploads'
145
+ config.cache_dir = 'uploads/tmp'
146
+ config.delete_tmp_file_after_storage = true
147
+ config.remove_previously_stored_files_after_update = true
148
+ config.ignore_integrity_errors = true
149
+ config.ignore_processing_errors = true
150
+ config.validate_integrity = true
151
+ config.validate_processing = true
152
+ config.root = CarrierWave.root
153
+ config.enable_processing = true
154
+ config.ensure_multipart_form = true
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+ end
161
+ end
162
+