carrierwave 0.3.5.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of carrierwave might be problematic. Click here for more details.
- data/Generators +1 -1
- data/History.txt +11 -0
- data/Manifest.txt +7 -5
- data/README.rdoc +67 -26
- data/Rakefile +4 -1
- data/features/grid_fs_storage.feature +32 -0
- data/features/step_definitions/general_steps.rb +6 -1
- data/features/support/env.rb +5 -16
- data/lib/carrierwave.rb +30 -61
- data/lib/carrierwave/compatibility/paperclip.rb +2 -2
- data/lib/carrierwave/core_ext/inheritable_attributes.rb +3 -3
- data/lib/carrierwave/mount.rb +34 -27
- data/lib/carrierwave/orm/activerecord.rb +2 -2
- data/lib/carrierwave/processing/rmagick.rb +1 -1
- data/lib/carrierwave/storage/abstract.rb +0 -2
- data/lib/carrierwave/storage/file.rb +3 -5
- data/lib/carrierwave/storage/grid_fs.rb +88 -0
- data/lib/carrierwave/storage/s3.rb +37 -69
- data/lib/carrierwave/uploader.rb +1 -2
- data/lib/carrierwave/uploader/cache.rb +21 -18
- data/lib/carrierwave/uploader/configuration.rb +59 -0
- data/lib/carrierwave/uploader/remove.rb +0 -1
- data/lib/carrierwave/uploader/store.rb +3 -30
- data/lib/carrierwave/uploader/url.rb +1 -1
- data/lib/carrierwave/uploader/versions.rb +1 -4
- data/{lib/generators → merb_generators}/uploader_generator.rb +0 -0
- data/rails_generators/uploader/templates/uploader.rb +3 -3
- data/spec/compatibility/paperclip_spec.rb +11 -2
- data/spec/mount_spec.rb +0 -25
- data/spec/orm/datamapper_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -3
- data/spec/storage/grid_fs_spec.rb +76 -0
- data/spec/storage/s3_spec.rb +75 -0
- data/spec/uploader/cache_spec.rb +1 -13
- data/spec/uploader/configuration_spec.rb +71 -0
- data/spec/uploader/paths_spec.rb +1 -1
- data/spec/uploader/store_spec.rb +0 -16
- data/spec/uploader/versions_spec.rb +0 -8
- metadata +40 -8
- data/carrierwave.gemspec +0 -63
- data/lib/carrierwave/uploader/default_path.rb +0 -24
- data/lib/carrierwave/uploader/paths.rb +0 -27
- data/spec/uploader/default_path_spec.rb +0 -68
@@ -78,8 +78,8 @@ module CarrierWave
|
|
78
78
|
|
79
79
|
def mappings
|
80
80
|
{
|
81
|
-
:rails_root => lambda{|u, f|
|
82
|
-
:rails_env => lambda{|u, f|
|
81
|
+
:rails_root => lambda{|u, f| Rails.root },
|
82
|
+
:rails_env => lambda{|u, f| Rails.env },
|
83
83
|
:class => lambda{|u, f| u.model.class.name.underscore.pluralize},
|
84
84
|
:id => lambda{|u, f| u.model.id },
|
85
85
|
:id_partition => lambda{|u, f| ("%09d" % u.model.id).scan(/\d{3}/).join("/")},
|
@@ -58,7 +58,7 @@ class Class
|
|
58
58
|
RUBY
|
59
59
|
end
|
60
60
|
end
|
61
|
-
end
|
61
|
+
end unless Class.respond_to?(:extlib_inheritable_reader)
|
62
62
|
|
63
63
|
# Defines class-level inheritable attribute writer. Attributes are available to subclasses,
|
64
64
|
# each subclass has a copy of parent's attribute.
|
@@ -86,7 +86,7 @@ class Class
|
|
86
86
|
RUBY
|
87
87
|
end
|
88
88
|
end
|
89
|
-
end
|
89
|
+
end unless Class.respond_to?(:extlib_inheritable_writer)
|
90
90
|
|
91
91
|
# Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
|
92
92
|
# each subclass has a copy of parent's attribute.
|
@@ -100,5 +100,5 @@ class Class
|
|
100
100
|
def extlib_inheritable_accessor(*syms)
|
101
101
|
extlib_inheritable_reader(*syms)
|
102
102
|
extlib_inheritable_writer(*syms)
|
103
|
-
end
|
103
|
+
end unless Class.respond_to?(:extlib_inheritable_accessor)
|
104
104
|
end
|
data/lib/carrierwave/mount.rb
CHANGED
@@ -26,11 +26,6 @@ module CarrierWave
|
|
26
26
|
@uploaders
|
27
27
|
end
|
28
28
|
|
29
|
-
##
|
30
|
-
# === Returns
|
31
|
-
#
|
32
|
-
# [Hash{Symbol => Hash}] options for mounted uploaders
|
33
|
-
#
|
34
29
|
def uploader_options
|
35
30
|
@uploader_options ||= {}
|
36
31
|
@uploader_options = superclass.uploader_options.merge(@uploader_options)
|
@@ -38,6 +33,26 @@ module CarrierWave
|
|
38
33
|
@uploader_options
|
39
34
|
end
|
40
35
|
|
36
|
+
##
|
37
|
+
# Return a particular option for a particular uploader
|
38
|
+
#
|
39
|
+
# === Parameters
|
40
|
+
#
|
41
|
+
# [column (Symbol)] The column the uploader is mounted at
|
42
|
+
# [option (Symbol)] The option, e.g. validate_integrity
|
43
|
+
#
|
44
|
+
# === Returns
|
45
|
+
#
|
46
|
+
# [Object] The option value
|
47
|
+
#
|
48
|
+
def uploader_option(column, option)
|
49
|
+
if uploader_options[column].has_key?(option)
|
50
|
+
uploader_options[column][option]
|
51
|
+
else
|
52
|
+
uploaders[column].send(option)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
41
56
|
##
|
42
57
|
# Mounts the given uploader on the given column. This means that assigning
|
43
58
|
# and reading from the column will upload and retrieve files. Supposing
|
@@ -70,9 +85,6 @@ module CarrierWave
|
|
70
85
|
# [image_cache] Returns a string that identifies the cache location of the file
|
71
86
|
# [image_cache=] Retrieves the file from the cache based on the given cache name
|
72
87
|
#
|
73
|
-
# [image_uploader] Returns an instance of the uploader
|
74
|
-
# [image_uploader=] Sets the uploader (be careful!)
|
75
|
-
#
|
76
88
|
# [remove_image] An attribute reader that can be used with a checkbox to mark a file for removal
|
77
89
|
# [remove_image=] An attribute writer that can be used with a checkbox to mark a file for removal
|
78
90
|
# [remove_image?] Whether the file should be removed when store_image! is called.
|
@@ -131,7 +143,7 @@ module CarrierWave
|
|
131
143
|
end
|
132
144
|
|
133
145
|
uploaders[column.to_sym] = uploader
|
134
|
-
uploader_options[column.to_sym] =
|
146
|
+
uploader_options[column.to_sym] = options
|
135
147
|
|
136
148
|
include CarrierWave::Mount::Extension
|
137
149
|
|
@@ -165,14 +177,6 @@ module CarrierWave
|
|
165
177
|
_mounter(:#{column}).url(*args)
|
166
178
|
end
|
167
179
|
|
168
|
-
def #{column}_uploader
|
169
|
-
_mounter(:#{column}).uploader
|
170
|
-
end
|
171
|
-
|
172
|
-
def #{column}_uploader=(uploader)
|
173
|
-
_mounter(:#{column}).uploader = uploader
|
174
|
-
end
|
175
|
-
|
176
180
|
def #{column}_cache
|
177
181
|
_mounter(:#{column}).cache_name
|
178
182
|
end
|
@@ -244,9 +248,8 @@ module CarrierWave
|
|
244
248
|
# we don't pollute the model with a lot of methods.
|
245
249
|
class Mounter #:nodoc:
|
246
250
|
|
247
|
-
attr_reader :column, :record, :
|
248
|
-
|
249
|
-
attr_accessor :uploader, :integrity_error, :processing_error, :remove
|
251
|
+
attr_reader :column, :record, :integrity_error, :processing_error
|
252
|
+
attr_accessor :remove
|
250
253
|
|
251
254
|
def initialize(record, column, options={})
|
252
255
|
@record = record
|
@@ -277,14 +280,14 @@ module CarrierWave
|
|
277
280
|
|
278
281
|
def cache(new_file)
|
279
282
|
uploader.cache!(new_file)
|
280
|
-
|
281
|
-
|
283
|
+
@integrity_error = nil
|
284
|
+
@processing_error = nil
|
282
285
|
rescue CarrierWave::IntegrityError => e
|
283
|
-
|
284
|
-
raise e unless
|
286
|
+
@integrity_error = e
|
287
|
+
raise e unless option(:ignore_integrity_errors)
|
285
288
|
rescue CarrierWave::ProcessingError => e
|
286
|
-
|
287
|
-
raise e unless
|
289
|
+
@processing_error = e
|
290
|
+
raise e unless option(:ignore_processing_errors)
|
288
291
|
end
|
289
292
|
|
290
293
|
def cache_name
|
@@ -323,9 +326,13 @@ module CarrierWave
|
|
323
326
|
end
|
324
327
|
|
325
328
|
private
|
329
|
+
|
330
|
+
def option(name)
|
331
|
+
record.class.uploader_option(column, name)
|
332
|
+
end
|
326
333
|
|
327
334
|
def serialization_column
|
328
|
-
|
335
|
+
option(:mount_on) || column
|
329
336
|
end
|
330
337
|
|
331
338
|
end # Mounter
|
@@ -16,8 +16,8 @@ module CarrierWave
|
|
16
16
|
alias_method :read_uploader, :read_attribute
|
17
17
|
alias_method :write_uploader, :write_attribute
|
18
18
|
|
19
|
-
validates_integrity_of column if
|
20
|
-
validates_processing_of column if
|
19
|
+
validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
|
20
|
+
validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
|
21
21
|
|
22
22
|
after_save "store_#{column}!"
|
23
23
|
before_save "write_#{column}_identifier"
|
@@ -22,9 +22,8 @@ module CarrierWave
|
|
22
22
|
# [CarrierWave::SanitizedFile] a sanitized file
|
23
23
|
#
|
24
24
|
def store!(file)
|
25
|
-
path = ::File.
|
26
|
-
|
27
|
-
file.move_to(path, CarrierWave.config[:permissions])
|
25
|
+
path = ::File.expand_path(uploader.store_path, uploader.root)
|
26
|
+
file.move_to(path, uploader.permissions)
|
28
27
|
file
|
29
28
|
end
|
30
29
|
|
@@ -40,8 +39,7 @@ module CarrierWave
|
|
40
39
|
# [CarrierWave::SanitizedFile] a sanitized file
|
41
40
|
#
|
42
41
|
def retrieve!(identifier)
|
43
|
-
path = ::File.
|
44
|
-
path = ::File.expand_path(path, uploader.public)
|
42
|
+
path = ::File.expand_path(uploader.store_path(identifier), uploader.root)
|
45
43
|
CarrierWave::SanitizedFile.new(path)
|
46
44
|
end
|
47
45
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'mongo'
|
3
|
+
require 'mongo/gridfs'
|
4
|
+
|
5
|
+
module CarrierWave
|
6
|
+
module Storage
|
7
|
+
|
8
|
+
##
|
9
|
+
# The GridFS store uses MongoDB's GridStore file storage system to store files
|
10
|
+
#
|
11
|
+
class GridFS < Abstract
|
12
|
+
|
13
|
+
class File
|
14
|
+
|
15
|
+
def initialize(uploader, database, path)
|
16
|
+
@database = database
|
17
|
+
@path = path
|
18
|
+
@uploader = uploader
|
19
|
+
end
|
20
|
+
|
21
|
+
def path
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def url
|
26
|
+
unless @uploader.grid_fs_access_url
|
27
|
+
nil
|
28
|
+
else
|
29
|
+
[@uploader.grid_fs_access_url, @path].join("/")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def read
|
34
|
+
::GridFS::GridStore.read(@database, @path)
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete
|
38
|
+
::GridFS::GridStore.unlink(@database, @path)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Store the file in MongoDB's GridFS GridStore
|
45
|
+
#
|
46
|
+
# === Parameters
|
47
|
+
#
|
48
|
+
# [file (CarrierWave::SanitizedFile)] the file to store
|
49
|
+
#
|
50
|
+
# === Returns
|
51
|
+
#
|
52
|
+
# [CarrierWave::SanitizedFile] a sanitized file
|
53
|
+
#
|
54
|
+
def store!(file)
|
55
|
+
::GridFS::GridStore.open(database, uploader.store_path, 'w') do |f|
|
56
|
+
f.write file.read
|
57
|
+
end
|
58
|
+
CarrierWave::Storage::GridFS::File.new(uploader, database, uploader.store_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Retrieve the file from MongoDB's GridFS GridStore
|
63
|
+
#
|
64
|
+
# === Parameters
|
65
|
+
#
|
66
|
+
# [identifier (String)] the filename of the file
|
67
|
+
#
|
68
|
+
# === Returns
|
69
|
+
#
|
70
|
+
# [CarrierWave::Storage::GridFS::File] a sanitized file
|
71
|
+
#
|
72
|
+
def retrieve!(identifier)
|
73
|
+
CarrierWave::Storage::GridFS::File.new(uploader, database, uploader.store_path(identifier))
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def database
|
79
|
+
@connection ||= begin
|
80
|
+
host = uploader.grid_fs_host
|
81
|
+
database = uploader.grid_fs_database
|
82
|
+
Mongo::Connection.new(host).db(database)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end # File
|
87
|
+
end # Storage
|
88
|
+
end # CarrierWave
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require 'aws/s3'
|
2
3
|
|
3
4
|
module CarrierWave
|
4
5
|
module Storage
|
@@ -8,13 +9,17 @@ module CarrierWave
|
|
8
9
|
# CarrierWave to connect to Amazon S3, you'll need to specify an access key id, secret key
|
9
10
|
# and bucket
|
10
11
|
#
|
11
|
-
# CarrierWave.
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# CarrierWave.configure do |config|
|
13
|
+
# config.s3_access_key_id = "xxxxxx"
|
14
|
+
# config.s3_secret_access_key = "xxxxxx"
|
15
|
+
# config.s3_bucket = "my_bucket_name"
|
16
|
+
# end
|
14
17
|
#
|
15
18
|
# You can also set the access policy for the uploaded files:
|
16
19
|
#
|
17
|
-
# CarrierWave.
|
20
|
+
# CarrierWave.configure do |config|
|
21
|
+
# config.s3_access = :public
|
22
|
+
# end
|
18
23
|
#
|
19
24
|
# Possible values are the 'canned access control policies' provided in the aws/s3 gem,
|
20
25
|
# they are:
|
@@ -31,23 +36,26 @@ module CarrierWave
|
|
31
36
|
#
|
32
37
|
# You can change the generated url to a cnamed domain by setting the cnamed config:
|
33
38
|
#
|
34
|
-
# CarrierWave.
|
39
|
+
# CarrierWave.configure do |config|
|
40
|
+
# config.s3_cnamed = true
|
41
|
+
# config.s3_bucket = 'bucketname.domain.tld'
|
42
|
+
# end
|
35
43
|
#
|
36
|
-
#
|
44
|
+
# Now the resulting url will be
|
37
45
|
#
|
38
|
-
# http://
|
46
|
+
# http://bucketname.domain.tld/path/to/file
|
39
47
|
#
|
40
48
|
# instead of
|
41
49
|
#
|
42
|
-
# http://s3.amazonaws.com/
|
50
|
+
# http://s3.amazonaws.com/bucketname.domain.tld/path/to/file
|
43
51
|
#
|
44
52
|
class S3 < Abstract
|
45
53
|
|
46
54
|
class File
|
47
55
|
|
48
|
-
def initialize(
|
56
|
+
def initialize(uploader, path)
|
57
|
+
@uploader = uploader
|
49
58
|
@path = path
|
50
|
-
@identifier = identifier
|
51
59
|
end
|
52
60
|
|
53
61
|
##
|
@@ -61,17 +69,6 @@ module CarrierWave
|
|
61
69
|
@path
|
62
70
|
end
|
63
71
|
|
64
|
-
##
|
65
|
-
# Returns the filename on S3
|
66
|
-
#
|
67
|
-
# === Returns
|
68
|
-
#
|
69
|
-
# [String] path to the file
|
70
|
-
#
|
71
|
-
def identifier
|
72
|
-
@identifier
|
73
|
-
end
|
74
|
-
|
75
72
|
##
|
76
73
|
# Reads the contents of the file from S3
|
77
74
|
#
|
@@ -80,14 +77,14 @@ module CarrierWave
|
|
80
77
|
# [String] contents of the file
|
81
78
|
#
|
82
79
|
def read
|
83
|
-
AWS::S3::S3Object.value @path,
|
80
|
+
AWS::S3::S3Object.value @path, @uploader.s3_bucket
|
84
81
|
end
|
85
82
|
|
86
83
|
##
|
87
84
|
# Remove the file from Amazon S3
|
88
85
|
#
|
89
86
|
def delete
|
90
|
-
AWS::S3::S3Object.delete @path,
|
87
|
+
AWS::S3::S3Object.delete @path, @uploader.s3_bucket
|
91
88
|
end
|
92
89
|
|
93
90
|
##
|
@@ -98,10 +95,10 @@ module CarrierWave
|
|
98
95
|
# [String] file's url
|
99
96
|
#
|
100
97
|
def url
|
101
|
-
if
|
102
|
-
["http://",
|
98
|
+
if @uploader.s3_cnamed
|
99
|
+
["http://", @uploader.s3_bucket, @path].compact.join('/')
|
103
100
|
else
|
104
|
-
["http://s3.amazonaws.com",
|
101
|
+
["http://s3.amazonaws.com", @uploader.s3_bucket, @path].compact.join('/')
|
105
102
|
end
|
106
103
|
end
|
107
104
|
|
@@ -137,46 +134,6 @@ module CarrierWave
|
|
137
134
|
@s3_object ||= AWS::S3::S3Object.find(@path, bucket)
|
138
135
|
end
|
139
136
|
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
def bucket
|
144
|
-
CarrierWave::Storage::S3.bucket
|
145
|
-
end
|
146
|
-
|
147
|
-
def access
|
148
|
-
CarrierWave::Storage::S3.access
|
149
|
-
end
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
##
|
154
|
-
# === Returns
|
155
|
-
#
|
156
|
-
# [String] the bucket set in the config options
|
157
|
-
#
|
158
|
-
def self.bucket
|
159
|
-
CarrierWave.config[:s3][:bucket]
|
160
|
-
end
|
161
|
-
|
162
|
-
##
|
163
|
-
# === Returns
|
164
|
-
#
|
165
|
-
# [Symbol] the access priviliges the uploaded files should have
|
166
|
-
#
|
167
|
-
def self.access
|
168
|
-
CarrierWave.config[:s3][:access]
|
169
|
-
end
|
170
|
-
|
171
|
-
##
|
172
|
-
# Connect to Amazon S3
|
173
|
-
#
|
174
|
-
def self.setup!
|
175
|
-
require 'aws/s3'
|
176
|
-
AWS::S3::Base.establish_connection!(
|
177
|
-
:access_key_id => CarrierWave.config[:s3][:access_key_id],
|
178
|
-
:secret_access_key => CarrierWave.config[:s3][:secret_access_key]
|
179
|
-
)
|
180
137
|
end
|
181
138
|
|
182
139
|
##
|
@@ -191,8 +148,9 @@ module CarrierWave
|
|
191
148
|
# [CarrierWave::Storage::S3] the stored file
|
192
149
|
#
|
193
150
|
def store!(file)
|
194
|
-
|
195
|
-
|
151
|
+
connect!(uploader)
|
152
|
+
AWS::S3::S3Object.store(uploader.store_path, file.read, uploader.s3_bucket, :access => uploader.s3_access)
|
153
|
+
CarrierWave::Storage::S3::File.new(uploader, uploader.store_path)
|
196
154
|
end
|
197
155
|
|
198
156
|
# Do something to retrieve the file
|
@@ -207,7 +165,17 @@ module CarrierWave
|
|
207
165
|
# [CarrierWave::Storage::S3::File] the stored file
|
208
166
|
#
|
209
167
|
def retrieve!(identifier)
|
210
|
-
|
168
|
+
connect!(uploader)
|
169
|
+
CarrierWave::Storage::S3::File.new(uploader, uploader.store_path(identifier))
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def connect!(uploader)
|
175
|
+
AWS::S3::Base.establish_connection!(
|
176
|
+
:access_key_id => uploader.s3_access_key_id,
|
177
|
+
:secret_access_key => uploader.s3_secret_access_key
|
178
|
+
)
|
211
179
|
end
|
212
180
|
|
213
181
|
end # S3
|