durran-carrierwave 0.3.2.3 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Generators +1 -1
- data/History.txt +39 -2
- data/Manifest.txt +19 -5
- data/README.rdoc +180 -55
- data/Rakefile +11 -4
- data/features/grid_fs_storage.feature +32 -0
- data/features/step_definitions/general_steps.rb +6 -1
- data/features/support/activerecord.rb +1 -1
- data/features/support/env.rb +3 -16
- data/lib/carrierwave.rb +19 -74
- data/lib/carrierwave/compatibility/paperclip.rb +2 -2
- data/lib/carrierwave/core_ext/inheritable_attributes.rb +3 -3
- data/lib/carrierwave/mount.rb +36 -27
- data/lib/carrierwave/orm/activerecord.rb +3 -3
- data/lib/carrierwave/orm/datamapper.rb +2 -2
- data/lib/carrierwave/orm/mongoid.rb +23 -0
- data/lib/carrierwave/orm/mongomapper.rb +1 -1
- data/lib/carrierwave/orm/sequel.rb +4 -16
- data/lib/carrierwave/processing/image_science.rb +54 -25
- data/lib/carrierwave/processing/mini_magick.rb +269 -0
- data/lib/carrierwave/processing/rmagick.rb +4 -6
- data/lib/carrierwave/sanitized_file.rb +7 -6
- data/lib/carrierwave/storage/abstract.rb +0 -2
- data/lib/carrierwave/storage/file.rb +3 -5
- data/lib/carrierwave/storage/grid_fs.rb +92 -0
- data/lib/carrierwave/storage/right_s3.rb +183 -0
- data/lib/carrierwave/storage/s3.rb +37 -69
- data/lib/carrierwave/test/matchers.rb +22 -8
- data/lib/carrierwave/uploader.rb +2 -2
- data/lib/carrierwave/uploader/cache.rb +21 -18
- data/lib/carrierwave/uploader/configuration.rb +122 -0
- data/lib/carrierwave/uploader/default_url.rb +19 -0
- data/lib/carrierwave/uploader/processing.rb +4 -2
- data/lib/carrierwave/uploader/remove.rb +0 -1
- data/lib/carrierwave/uploader/store.rb +1 -68
- data/lib/carrierwave/uploader/url.rb +1 -1
- data/lib/carrierwave/uploader/versions.rb +3 -4
- data/{lib/generators → merb_generators}/uploader_generator.rb +0 -0
- data/rails_generators/uploader/templates/uploader.rb +4 -4
- data/spec/compatibility/paperclip_spec.rb +11 -2
- data/spec/fixtures/landscape.jpg +0 -0
- data/spec/fixtures/portrait.jpg +0 -0
- data/spec/mount_spec.rb +0 -25
- data/spec/orm/datamapper_spec.rb +55 -48
- data/spec/orm/mongoid_spec.rb +206 -0
- data/spec/orm/mongomapper_spec.rb +19 -1
- data/spec/orm/sequel_spec.rb +3 -12
- data/spec/processing/image_science_spec.rb +56 -0
- data/spec/processing/mini_magick_spec.rb +76 -0
- data/spec/processing/rmagick_spec.rb +68 -0
- data/spec/sanitized_file_spec.rb +84 -74
- data/spec/spec_helper.rb +1 -3
- data/spec/storage/grid_fs_spec.rb +78 -0
- data/spec/storage/right_s3_spec.rb +75 -0
- data/spec/storage/s3_spec.rb +83 -0
- data/spec/uploader/cache_spec.rb +1 -13
- data/spec/uploader/configuration_spec.rb +105 -0
- data/spec/uploader/{default_path_spec.rb → default_url_spec.rb} +22 -5
- data/spec/uploader/paths_spec.rb +1 -1
- data/spec/uploader/processing_spec.rb +11 -0
- data/spec/uploader/store_spec.rb +21 -47
- data/spec/uploader/versions_spec.rb +0 -8
- metadata +105 -17
- data/LICENSE +0 -8
- data/carrierwave.gemspec +0 -57
- data/lib/carrierwave/uploader/default_path.rb +0 -23
- data/lib/carrierwave/uploader/paths.rb +0 -27
@@ -61,23 +61,23 @@ module CarrierWave
|
|
61
61
|
def matches?(actual)
|
62
62
|
@actual = actual
|
63
63
|
# Satisfy expectation here. Return false or raise an error if it's not met.
|
64
|
-
|
65
|
-
img = ::Magick::Image.read(@actual.path).first
|
64
|
+
img = ::Magick::Image.read(@actual.current_path).first
|
66
65
|
@actual_width = img.columns
|
67
66
|
@actual_height = img.rows
|
68
67
|
@actual_width <= @width && @actual_height <= @height
|
69
68
|
end
|
70
69
|
|
71
70
|
def failure_message
|
72
|
-
"expected #{@actual.inspect} to be no larger than #{@width} by #{@height}, but it was #{@
|
71
|
+
"expected #{@actual.current_path.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
|
73
72
|
end
|
74
73
|
|
75
74
|
def negative_failure_message
|
76
|
-
"expected #{@actual.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
|
75
|
+
"expected #{@actual.current_path.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
|
77
76
|
end
|
78
77
|
end
|
79
78
|
|
80
79
|
def be_no_larger_than(width, height)
|
80
|
+
load_rmagick
|
81
81
|
BeNoLargerThan.new(width, height)
|
82
82
|
end
|
83
83
|
|
@@ -89,25 +89,39 @@ module CarrierWave
|
|
89
89
|
def matches?(actual)
|
90
90
|
@actual = actual
|
91
91
|
# Satisfy expectation here. Return false or raise an error if it's not met.
|
92
|
-
|
93
|
-
img = ::Magick::Image.read(@actual.path).first
|
92
|
+
img = ::Magick::Image.read(@actual.current_path).first
|
94
93
|
@actual_width = img.columns
|
95
94
|
@actual_height = img.rows
|
96
95
|
@actual_width == @width && @actual_height == @height
|
97
96
|
end
|
98
97
|
|
99
98
|
def failure_message
|
100
|
-
"expected #{@actual.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@
|
99
|
+
"expected #{@actual.current_path.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
|
101
100
|
end
|
102
101
|
|
103
102
|
def negative_failure_message
|
104
|
-
"expected #{@actual.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
|
103
|
+
"expected #{@actual.current_path.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
|
105
104
|
end
|
106
105
|
end
|
107
106
|
|
108
107
|
def have_dimensions(width, height)
|
108
|
+
load_rmagick
|
109
109
|
HaveDimensions.new(width, height)
|
110
110
|
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def load_rmagick
|
115
|
+
unless defined? Magick
|
116
|
+
begin
|
117
|
+
require 'rmagick'
|
118
|
+
rescue LoadError
|
119
|
+
require 'RMagick'
|
120
|
+
rescue LoadError
|
121
|
+
puts "WARNING: Failed to require rmagick, image processing may fail!"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
111
125
|
|
112
126
|
end # SpecHelper
|
113
127
|
end # Test
|
data/lib/carrierwave/uploader.rb
CHANGED
@@ -25,7 +25,6 @@ module CarrierWave
|
|
25
25
|
class Base
|
26
26
|
attr_reader :file
|
27
27
|
|
28
|
-
use CarrierWave::Uploader::Paths
|
29
28
|
use CarrierWave::Uploader::Callbacks
|
30
29
|
use CarrierWave::Uploader::Proxy
|
31
30
|
use CarrierWave::Uploader::Url
|
@@ -34,9 +33,10 @@ module CarrierWave
|
|
34
33
|
use CarrierWave::Uploader::Store
|
35
34
|
use CarrierWave::Uploader::Remove
|
36
35
|
use CarrierWave::Uploader::ExtensionWhitelist
|
37
|
-
use CarrierWave::Uploader::DefaultPath
|
38
36
|
use CarrierWave::Uploader::Processing
|
39
37
|
use CarrierWave::Uploader::Versions
|
38
|
+
use CarrierWave::Uploader::DefaultUrl
|
39
|
+
use CarrierWave::Uploader::Configuration
|
40
40
|
end # Base
|
41
41
|
|
42
42
|
end # Uploader
|
@@ -1,11 +1,29 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
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
|
+
|
4
22
|
module Uploader
|
5
23
|
module Cache
|
6
24
|
|
7
|
-
depends_on CarrierWave::Uploader::Paths
|
8
25
|
depends_on CarrierWave::Uploader::Callbacks
|
26
|
+
depends_on CarrierWave::Uploader::Configuration
|
9
27
|
|
10
28
|
##
|
11
29
|
# Returns true if the uploader has been cached
|
@@ -18,17 +36,6 @@ module CarrierWave
|
|
18
36
|
@cache_id
|
19
37
|
end
|
20
38
|
|
21
|
-
##
|
22
|
-
# Override this in your Uploader to change the directory where files are cached.
|
23
|
-
#
|
24
|
-
# === Returns
|
25
|
-
#
|
26
|
-
# [String] a directory
|
27
|
-
#
|
28
|
-
def cache_dir
|
29
|
-
CarrierWave.config[:cache_dir]
|
30
|
-
end
|
31
|
-
|
32
39
|
##
|
33
40
|
# Returns a String which uniquely identifies the currently cached file for later retrieval
|
34
41
|
#
|
@@ -62,11 +69,7 @@ module CarrierWave
|
|
62
69
|
@filename = new_file.filename
|
63
70
|
self.original_filename = new_file.filename
|
64
71
|
|
65
|
-
|
66
|
-
@file = new_file.copy_to(cache_path, CarrierWave.config[:permissions])
|
67
|
-
else
|
68
|
-
@file = new_file
|
69
|
-
end
|
72
|
+
@file = new_file.copy_to(cache_path, permissions)
|
70
73
|
end
|
71
74
|
end
|
72
75
|
end
|
@@ -93,7 +96,7 @@ module CarrierWave
|
|
93
96
|
private
|
94
97
|
|
95
98
|
def cache_path
|
96
|
-
File.expand_path(File.join(cache_dir, cache_name),
|
99
|
+
File.expand_path(File.join(cache_dir, cache_name), root)
|
97
100
|
end
|
98
101
|
|
99
102
|
attr_reader :cache_id, :original_filename
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
|
3
|
+
module Uploader
|
4
|
+
module Configuration
|
5
|
+
setup do
|
6
|
+
add_config :root
|
7
|
+
add_config :permissions
|
8
|
+
add_config :storage_engines
|
9
|
+
add_config :s3_access # for aws/s3
|
10
|
+
add_config :s3_access_policy # for right_aws
|
11
|
+
add_config :s3_bucket
|
12
|
+
add_config :s3_access_key_id
|
13
|
+
add_config :s3_secret_access_key
|
14
|
+
add_config :s3_cnamed
|
15
|
+
add_config :grid_fs_database
|
16
|
+
add_config :grid_fs_host
|
17
|
+
add_config :grid_fs_username
|
18
|
+
add_config :grid_fs_password
|
19
|
+
add_config :grid_fs_access_url
|
20
|
+
add_config :store_dir
|
21
|
+
add_config :cache_dir
|
22
|
+
add_config :enable_processing
|
23
|
+
|
24
|
+
# Mounting
|
25
|
+
add_config :ignore_integrity_errors
|
26
|
+
add_config :ignore_processing_errors
|
27
|
+
add_config :validate_integrity
|
28
|
+
add_config :validate_processing
|
29
|
+
add_config :mount_on
|
30
|
+
|
31
|
+
configure do |config|
|
32
|
+
config.permissions = 0644
|
33
|
+
config.storage_engines = {
|
34
|
+
:file => "CarrierWave::Storage::File",
|
35
|
+
:s3 => "CarrierWave::Storage::S3",
|
36
|
+
:grid_fs => "CarrierWave::Storage::GridFS",
|
37
|
+
:right_s3 => "CarrierWave::Storage::RightS3"
|
38
|
+
}
|
39
|
+
config.storage = :file
|
40
|
+
config.s3_access = :public_read
|
41
|
+
config.s3_access_policy = 'public-read'
|
42
|
+
config.grid_fs_database = 'carrierwave'
|
43
|
+
config.grid_fs_host = 'localhost'
|
44
|
+
config.store_dir = 'uploads'
|
45
|
+
config.cache_dir = 'uploads/tmp'
|
46
|
+
config.ignore_integrity_errors = true
|
47
|
+
config.ignore_processing_errors = true
|
48
|
+
config.validate_integrity = true
|
49
|
+
config.validate_processing = true
|
50
|
+
config.root = CarrierWave.root
|
51
|
+
config.enable_processing = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module ClassMethods
|
56
|
+
|
57
|
+
##
|
58
|
+
# Sets the storage engine to be used when storing files with this uploader.
|
59
|
+
# Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
|
60
|
+
# method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
|
61
|
+
# be added to CarrierWave::Uploader::Base.storage_engines so they can be referred
|
62
|
+
# to by a symbol, which should be more convenient
|
63
|
+
#
|
64
|
+
# If no argument is given, it will simply return the currently used storage engine.
|
65
|
+
#
|
66
|
+
# === Parameters
|
67
|
+
#
|
68
|
+
# [storage (Symbol, Class)] The storage engine to use for this uploader
|
69
|
+
#
|
70
|
+
# === Returns
|
71
|
+
#
|
72
|
+
# [Class] the storage engine to be used with this uploader
|
73
|
+
#
|
74
|
+
# === Examples
|
75
|
+
#
|
76
|
+
# storage :file
|
77
|
+
# storage CarrierWave::Storage::File
|
78
|
+
# storage MyCustomStorageEngine
|
79
|
+
#
|
80
|
+
def storage(storage = nil)
|
81
|
+
if storage.is_a?(Symbol)
|
82
|
+
@storage = eval(storage_engines[storage])
|
83
|
+
elsif storage
|
84
|
+
@storage = storage
|
85
|
+
elsif @storage.nil?
|
86
|
+
# Get the storage from the superclass if there is one
|
87
|
+
@storage = superclass.storage rescue nil
|
88
|
+
end
|
89
|
+
return @storage
|
90
|
+
end
|
91
|
+
alias_method :storage=, :storage
|
92
|
+
|
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
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module DefaultUrl
|
6
|
+
|
7
|
+
def url(*args)
|
8
|
+
super || default_url
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Override this method in your uploader to provide a default url
|
13
|
+
# in case no file has been cached/stored yet.
|
14
|
+
#
|
15
|
+
def default_url; end
|
16
|
+
|
17
|
+
end # DefaultPath
|
18
|
+
end # Uploader
|
19
|
+
end # CarrierWave
|
@@ -71,8 +71,10 @@ module CarrierWave
|
|
71
71
|
# Apply all process callbacks added through CarrierWave.process
|
72
72
|
#
|
73
73
|
def process!(new_file=nil)
|
74
|
-
|
75
|
-
self.
|
74
|
+
if enable_processing
|
75
|
+
self.class.processors.each do |method, args|
|
76
|
+
self.send(method, *args)
|
77
|
+
end
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
@@ -4,64 +4,10 @@ module CarrierWave
|
|
4
4
|
module Uploader
|
5
5
|
module Store
|
6
6
|
|
7
|
-
depends_on CarrierWave::Uploader::Paths
|
8
7
|
depends_on CarrierWave::Uploader::Callbacks
|
8
|
+
depends_on CarrierWave::Uploader::Configuration
|
9
9
|
depends_on CarrierWave::Uploader::Cache
|
10
10
|
|
11
|
-
module ClassMethods
|
12
|
-
|
13
|
-
##
|
14
|
-
# Sets the storage engine to be used when storing files with this uploader.
|
15
|
-
# Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
|
16
|
-
# method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
|
17
|
-
# be added to CarrierWave.config[:storage_engines] so they can be referred
|
18
|
-
# to by a symbol, which should be more convenient
|
19
|
-
#
|
20
|
-
# If no argument is given, it will simply return the currently used storage engine.
|
21
|
-
#
|
22
|
-
# === Parameters
|
23
|
-
#
|
24
|
-
# [storage (Symbol, Class)] The storage engine to use for this uploader
|
25
|
-
#
|
26
|
-
# === Returns
|
27
|
-
#
|
28
|
-
# [Class] the storage engine to be used with this uploader
|
29
|
-
#
|
30
|
-
# === Examples
|
31
|
-
#
|
32
|
-
# storage :file
|
33
|
-
# storage CarrierWave::Storage::File
|
34
|
-
# storage MyCustomStorageEngine
|
35
|
-
#
|
36
|
-
def storage(storage = nil)
|
37
|
-
if storage.is_a?(Symbol)
|
38
|
-
@storage = get_storage_by_symbol(storage)
|
39
|
-
@storage.setup!
|
40
|
-
elsif storage
|
41
|
-
@storage = storage
|
42
|
-
@storage.setup!
|
43
|
-
elsif @storage.nil?
|
44
|
-
# Get the storage from the superclass if there is one
|
45
|
-
@storage = superclass.storage rescue nil
|
46
|
-
end
|
47
|
-
if @storage.nil?
|
48
|
-
# If we were not able to find a store any other way, setup the default store
|
49
|
-
@storage ||= get_storage_by_symbol(CarrierWave.config[:storage])
|
50
|
-
@storage.setup!
|
51
|
-
end
|
52
|
-
return @storage
|
53
|
-
end
|
54
|
-
|
55
|
-
alias_method :storage=, :storage
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def get_storage_by_symbol(symbol)
|
60
|
-
eval(CarrierWave.config[:storage_engines][symbol])
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
11
|
##
|
66
12
|
# Override this in your Uploader to change the filename.
|
67
13
|
#
|
@@ -80,19 +26,6 @@ module CarrierWave
|
|
80
26
|
@filename
|
81
27
|
end
|
82
28
|
|
83
|
-
##
|
84
|
-
# Override this in your Uploader to change the directory where the file backend stores files.
|
85
|
-
#
|
86
|
-
# Other backends may or may not use this method, depending on their specific needs.
|
87
|
-
#
|
88
|
-
# === Returns
|
89
|
-
#
|
90
|
-
# [String] a directory
|
91
|
-
#
|
92
|
-
def store_dir
|
93
|
-
CarrierWave.config[:store_dir]
|
94
|
-
end
|
95
|
-
|
96
29
|
##
|
97
30
|
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
|
98
31
|
# used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
|
@@ -4,6 +4,8 @@ module CarrierWave
|
|
4
4
|
module Uploader
|
5
5
|
module Versions
|
6
6
|
|
7
|
+
depends_on CarrierWave::Uploader::Callbacks
|
8
|
+
|
7
9
|
setup do
|
8
10
|
after :cache, :cache_versions!
|
9
11
|
after :store, :store_versions!
|
@@ -128,10 +130,7 @@ module CarrierWave
|
|
128
130
|
end
|
129
131
|
|
130
132
|
def remove_versions!
|
131
|
-
versions.each
|
132
|
-
CarrierWave.logger.info "CarrierWave: removing file for version #{v.version_name}"
|
133
|
-
v.remove!
|
134
|
-
end
|
133
|
+
versions.each { |name, v| v.remove! }
|
135
134
|
end
|
136
135
|
|
137
136
|
def retrieve_versions_from_cache!(cache_name)
|
File without changes
|
@@ -16,9 +16,9 @@ class <%= class_name %>Uploader < CarrierWave::Uploader::Base
|
|
16
16
|
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
17
17
|
end
|
18
18
|
|
19
|
-
# Provide a default
|
20
|
-
# def
|
21
|
-
# "images/fallback/" + [version_name, "default.png"].compact.join('_')
|
19
|
+
# Provide a default URL as a default if there hasn't been a file uploaded
|
20
|
+
# def default_url
|
21
|
+
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
|
22
22
|
# end
|
23
23
|
|
24
24
|
# Process files as they are uploaded.
|
@@ -41,7 +41,7 @@ class <%= class_name %>Uploader < CarrierWave::Uploader::Base
|
|
41
41
|
|
42
42
|
# Override the filename of the uploaded files
|
43
43
|
# def filename
|
44
|
-
# "something.jpg"
|
44
|
+
# "something.jpg" if original_filename
|
45
45
|
# end
|
46
46
|
|
47
47
|
end
|