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.

Files changed (43) hide show
  1. data/Generators +1 -1
  2. data/History.txt +11 -0
  3. data/Manifest.txt +7 -5
  4. data/README.rdoc +67 -26
  5. data/Rakefile +4 -1
  6. data/features/grid_fs_storage.feature +32 -0
  7. data/features/step_definitions/general_steps.rb +6 -1
  8. data/features/support/env.rb +5 -16
  9. data/lib/carrierwave.rb +30 -61
  10. data/lib/carrierwave/compatibility/paperclip.rb +2 -2
  11. data/lib/carrierwave/core_ext/inheritable_attributes.rb +3 -3
  12. data/lib/carrierwave/mount.rb +34 -27
  13. data/lib/carrierwave/orm/activerecord.rb +2 -2
  14. data/lib/carrierwave/processing/rmagick.rb +1 -1
  15. data/lib/carrierwave/storage/abstract.rb +0 -2
  16. data/lib/carrierwave/storage/file.rb +3 -5
  17. data/lib/carrierwave/storage/grid_fs.rb +88 -0
  18. data/lib/carrierwave/storage/s3.rb +37 -69
  19. data/lib/carrierwave/uploader.rb +1 -2
  20. data/lib/carrierwave/uploader/cache.rb +21 -18
  21. data/lib/carrierwave/uploader/configuration.rb +59 -0
  22. data/lib/carrierwave/uploader/remove.rb +0 -1
  23. data/lib/carrierwave/uploader/store.rb +3 -30
  24. data/lib/carrierwave/uploader/url.rb +1 -1
  25. data/lib/carrierwave/uploader/versions.rb +1 -4
  26. data/{lib/generators → merb_generators}/uploader_generator.rb +0 -0
  27. data/rails_generators/uploader/templates/uploader.rb +3 -3
  28. data/spec/compatibility/paperclip_spec.rb +11 -2
  29. data/spec/mount_spec.rb +0 -25
  30. data/spec/orm/datamapper_spec.rb +1 -1
  31. data/spec/spec_helper.rb +3 -3
  32. data/spec/storage/grid_fs_spec.rb +76 -0
  33. data/spec/storage/s3_spec.rb +75 -0
  34. data/spec/uploader/cache_spec.rb +1 -13
  35. data/spec/uploader/configuration_spec.rb +71 -0
  36. data/spec/uploader/paths_spec.rb +1 -1
  37. data/spec/uploader/store_spec.rb +0 -16
  38. data/spec/uploader/versions_spec.rb +0 -8
  39. metadata +40 -8
  40. data/carrierwave.gemspec +0 -63
  41. data/lib/carrierwave/uploader/default_path.rb +0 -24
  42. data/lib/carrierwave/uploader/paths.rb +0 -27
  43. 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| CarrierWave.config[:root] },
82
- :rails_env => lambda{|u, f| CarrierWave.config[:env] },
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
@@ -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] = CarrierWave.config[:mount].merge(options)
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, :options
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
- self.integrity_error = nil
281
- self.processing_error = nil
283
+ @integrity_error = nil
284
+ @processing_error = nil
282
285
  rescue CarrierWave::IntegrityError => e
283
- self.integrity_error = e
284
- raise e unless options[:ignore_integrity_errors]
286
+ @integrity_error = e
287
+ raise e unless option(:ignore_integrity_errors)
285
288
  rescue CarrierWave::ProcessingError => e
286
- self.processing_error = e
287
- raise e unless options[:ignore_processing_errors]
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
- options[:mount_on] || column
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 uploader_options[column.to_sym][:validate_integrity]
20
- validates_processing_of column if uploader_options[column.to_sym][:validate_processing]
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"
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- unless Module.const_defined?('Magick')
3
+ unless defined? Magick
4
4
  begin
5
5
  require 'rmagick'
6
6
  rescue LoadError
@@ -15,8 +15,6 @@ module CarrierWave
15
15
  @uploader = uploader
16
16
  end
17
17
 
18
- def self.setup!; end
19
-
20
18
  def identifier
21
19
  uploader.filename
22
20
  end
@@ -22,9 +22,8 @@ module CarrierWave
22
22
  # [CarrierWave::SanitizedFile] a sanitized file
23
23
  #
24
24
  def store!(file)
25
- path = ::File.join(uploader.store_path)
26
- path = ::File.expand_path(path, uploader.public)
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.join(uploader.store_path(identifier))
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.config[:s3][:access_key_id] = "xxxxxx"
12
- # CarrierWave.config[:s3][:secret_access_key] = "xxxxxx"
13
- # CarrierWave.config[:s3][:bucket] = "my_bucket_name"
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.config[:s3][:access] = :public_read
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.config[:s3][:cnamed] = true
39
+ # CarrierWave.configure do |config|
40
+ # config.s3_cnamed = true
41
+ # config.s3_bucket = 'bucketname.domain.tld'
42
+ # end
35
43
  #
36
- # No the resulting url will be
44
+ # Now the resulting url will be
37
45
  #
38
- # http://bucket_name.domain.tld/path/to/file
46
+ # http://bucketname.domain.tld/path/to/file
39
47
  #
40
48
  # instead of
41
49
  #
42
- # http://s3.amazonaws.com/bucket_name.domain.tld/path/to/file
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(path, identifier)
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, bucket
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, bucket
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 CarrierWave::config[:s3][:cnamed]
102
- ["http://", bucket, @path].compact.join('/')
98
+ if @uploader.s3_cnamed
99
+ ["http://", @uploader.s3_bucket, @path].compact.join('/')
103
100
  else
104
- ["http://s3.amazonaws.com", bucket, @path].compact.join('/')
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
- AWS::S3::S3Object.store(::File.join(uploader.store_path), file.read, self.class.bucket, :access => self.class.access)
195
- CarrierWave::Storage::S3::File.new(uploader.store_path, uploader.filename)
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
- CarrierWave::Storage::S3::File.new(uploader.store_path(identifier), identifier)
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