carrierwave 0.5.8 → 0.6.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.

@@ -4,13 +4,7 @@ require 'fileutils'
4
4
  require 'active_support/core_ext/object/blank'
5
5
  require 'active_support/core_ext/class/attribute'
6
6
 
7
- begin
8
- require 'active_support/core_ext/class/inheritable_attributes'
9
- rescue LoadError
10
- end
11
-
12
7
  require 'active_support/concern'
13
- require 'active_support/memoizable'
14
8
 
15
9
  module CarrierWave
16
10
 
@@ -44,10 +38,6 @@ module CarrierWave
44
38
  autoload :Abstract, 'carrierwave/storage/abstract'
45
39
  autoload :File, 'carrierwave/storage/file'
46
40
  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
41
  end
52
42
 
53
43
  module Uploader
@@ -65,6 +55,7 @@ module CarrierWave
65
55
  autoload :Url, 'carrierwave/uploader/url'
66
56
  autoload :Mountable, 'carrierwave/uploader/mountable'
67
57
  autoload :Configuration, 'carrierwave/uploader/configuration'
58
+ autoload :Serialization, 'carrierwave/uploader/serialization'
68
59
  end
69
60
 
70
61
  module Compatibility
@@ -104,13 +95,17 @@ elsif defined?(Rails)
104
95
  end
105
96
 
106
97
  elsif defined?(Sinatra)
107
-
108
- CarrierWave.root = if Sinatra::Application.respond_to?(:public_folder)
109
- # Sinatra >= 1.3
110
- Sinatra::Application.public_folder
98
+ if defined?(Padrino)
99
+ CarrierWave.root = File.join(PADRINO_ROOT, "public")
111
100
  else
112
- # Sinatra < 1.3
113
- Sinatra::Application.public
101
+
102
+ CarrierWave.root = if Sinatra::Application.respond_to?(:public_folder)
103
+ # Sinatra >= 1.3
104
+ Sinatra::Application.public_folder
105
+ else
106
+ # Sinatra < 1.3
107
+ Sinatra::Application.public
108
+ end
114
109
  end
115
110
 
116
111
  end
@@ -281,8 +281,6 @@ module CarrierWave
281
281
  # this is an internal class, used by CarrierWave::Mount so that
282
282
  # we don't pollute the model with a lot of methods.
283
283
  class Mounter #:nodoc:
284
- extend ActiveSupport::Memoizable
285
-
286
284
  attr_reader :column, :record, :remote_url, :integrity_error, :processing_error
287
285
  attr_accessor :remove
288
286
 
@@ -369,12 +367,14 @@ module CarrierWave
369
367
  option(:mount_on) || column
370
368
  end
371
369
 
370
+ attr_accessor :uploader_options
371
+
372
372
  private
373
373
 
374
374
  def option(name)
375
- record.class.uploader_option(column, name)
375
+ self.uploader_options ||= {}
376
+ self.uploader_options[name] ||= record.class.uploader_option(column, name)
376
377
  end
377
- memoize :option
378
378
 
379
379
  end # Mounter
380
380
 
@@ -36,6 +36,22 @@ module CarrierWave
36
36
  send(:"\#{column}_will_change!")
37
37
  super
38
38
  end
39
+
40
+ def remote_#{column}_url=(url)
41
+ column = _mounter(:#{column}).serialization_column
42
+ send(:"\#{column}_will_change!")
43
+ super
44
+ end
45
+
46
+ def serializable_hash(options=nil)
47
+ hash = {}
48
+ self.class.uploaders.each do |column, uploader|
49
+ if (!options[:only] && !options[:except]) || (options[:only] && options[:only].include?(column)) || (options[:except] && !options[:except].include?(column))
50
+ hash[column.to_s] = _mounter(:#{column}).uploader.serializable_hash
51
+ end
52
+ end
53
+ super(options).merge(hash)
54
+ end
39
55
  RUBY
40
56
 
41
57
  end
@@ -47,7 +47,7 @@ module CarrierWave
47
47
  if file.respond_to?(:content_type=)
48
48
  file.content_type = new_content_type
49
49
  else
50
- file.set_instance_variable(:@content_type, new_content_type)
50
+ file.instance_variable_set(:@content_type, new_content_type)
51
51
  end
52
52
  end
53
53
  rescue ::MIME::InvalidContentType => e
@@ -70,8 +70,8 @@ module CarrierWave
70
70
  process :resize_to_fit => [width, height]
71
71
  end
72
72
 
73
- def resize_to_fill(width, height)
74
- process :resize_to_fill => [width, height]
73
+ def resize_to_fill(width, height, gravity='Center')
74
+ process :resize_to_fill => [width, height, gravity]
75
75
  end
76
76
 
77
77
  def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
@@ -158,6 +158,7 @@ module CarrierWave
158
158
  #
159
159
  # [width (Integer)] the width to scale the image to
160
160
  # [height (Integer)] the height to scale the image to
161
+ # [gravity (String)] the current gravity suggestion (default: 'Center'; options: 'NorthWest', 'North', 'NorthEast', 'West', 'Center', 'East', 'SouthWest', 'South', 'SouthEast')
161
162
  #
162
163
  # === Yields
163
164
  #
@@ -174,6 +175,7 @@ module CarrierWave
174
175
  cmd.resize "#{cols}x#{rows}"
175
176
  end
176
177
  cmd.gravity gravity
178
+ cmd.background "rgba(255,255,255,0.0)"
177
179
  cmd.extent "#{width}x#{height}" if cols != width || rows != height
178
180
  end
179
181
  img = yield(img) if block_given?
@@ -206,7 +208,7 @@ module CarrierWave
206
208
  img.combine_options do |cmd|
207
209
  cmd.thumbnail "#{width}x#{height}>"
208
210
  if background == :transparent
209
- cmd.background "rgba(0, 0, 0, 0.0)"
211
+ cmd.background "rgba(255, 255, 255, 0.0)"
210
212
  else
211
213
  cmd.background background
212
214
  end
@@ -250,9 +250,9 @@ module CarrierWave
250
250
  frames = if image.size > 1
251
251
  list = ::Magick::ImageList.new
252
252
  image.each do |frame|
253
- list << yield( frame )
253
+ list << (block_given? ? yield( frame ) : frame)
254
254
  end
255
- list
255
+ block_given? ? list : list.append(true)
256
256
  else
257
257
  frame = image.first
258
258
  frame = yield( frame ) if block_given?
@@ -132,7 +132,7 @@ module CarrierWave
132
132
  # [Boolean] whether the file is valid and has a non-zero size
133
133
  #
134
134
  def empty?
135
- @file.nil? || self.size.nil? || self.size.zero?
135
+ @file.nil? || self.size.nil? || (self.size.zero? && ! self.exists?)
136
136
  end
137
137
 
138
138
  ##
@@ -238,7 +238,7 @@ module CarrierWave
238
238
  #
239
239
  def content_type
240
240
  return @content_type if @content_type
241
- @file.content_type.chomp if @file.respond_to?(:content_type) and @file.content_type
241
+ @file.content_type.to_s.chomp if @file.respond_to?(:content_type) and @file.content_type
242
242
  end
243
243
 
244
244
  ##
@@ -13,11 +13,11 @@ module CarrierWave
13
13
  ##
14
14
  # Move the file to the uploader's store path.
15
15
  #
16
- # By default, store!() uses copy_to(), which operates by copying the file
17
- # from the cache to the store, then deleting the file from the cache.
16
+ # By default, store!() uses copy_to(), which operates by copying the file
17
+ # from the cache to the store, then deleting the file from the cache.
18
18
  # If move_to_store() is overriden to return true, then store!() uses move_to(),
19
19
  # which simply moves the file from cache to store. Useful for large files.
20
- #
20
+ #
21
21
  # === Parameters
22
22
  #
23
23
  # [file (CarrierWave::SanitizedFile)] the file to store
@@ -62,6 +62,11 @@ module CarrierWave
62
62
  # end
63
63
  #
64
64
  class Fog < Abstract
65
+ class << self
66
+ def connection_cache
67
+ @connection_cache ||= {}
68
+ end
69
+ end
65
70
 
66
71
  ##
67
72
  # Store a file
@@ -97,7 +102,8 @@ module CarrierWave
97
102
 
98
103
  def connection
99
104
  @connection ||= begin
100
- ::Fog::Storage.new(uploader.fog_credentials)
105
+ credentials = uploader.fog_credentials
106
+ self.class.connection_cache[credentials] ||= ::Fog::Storage.new(credentials)
101
107
  end
102
108
  end
103
109
 
@@ -133,12 +139,16 @@ module CarrierWave
133
139
  # or
134
140
  # [NilClass] no authenticated url available
135
141
  #
136
- def authenticated_url
142
+ def authenticated_url(options = {})
137
143
  if ['AWS', 'Google'].include?(@uploader.fog_credentials[:provider])
138
144
  # avoid a get by using local references
139
145
  local_directory = connection.directories.new(:key => @uploader.fog_directory)
140
146
  local_file = local_directory.files.new(:key => path)
141
- local_file.url(::Fog::Time.now + @uploader.fog_authenticated_url_expiration)
147
+ if @uploader.fog_credentials[:provider] == "AWS"
148
+ local_file.url(::Fog::Time.now + @uploader.fog_authenticated_url_expiration, options)
149
+ else
150
+ local_file.url(::Fog::Time.now + @uploader.fog_authenticated_url_expiration)
151
+ end
142
152
  else
143
153
  nil
144
154
  end
@@ -218,6 +228,16 @@ module CarrierWave
218
228
  file.content_length
219
229
  end
220
230
 
231
+ ##
232
+ # Check if the file exists on the remote service
233
+ #
234
+ # === Returns
235
+ #
236
+ # [Boolean] true if file exists or false
237
+ def exists?
238
+ !!directory.files.head(path)
239
+ end
240
+
221
241
  ##
222
242
  # Write file to service
223
243
  #
@@ -233,6 +253,7 @@ module CarrierWave
233
253
  :key => path,
234
254
  :public => @uploader.fog_public
235
255
  }.merge(@uploader.fog_attributes))
256
+ fog_file.close if fog_file && !fog_file.closed?
236
257
  true
237
258
  end
238
259
 
@@ -247,13 +268,17 @@ module CarrierWave
247
268
  #
248
269
  def public_url
249
270
  if host = @uploader.fog_host
250
- "#{host}/#{path}"
271
+ if host.respond_to? :call
272
+ "#{host.call(self)}/#{path}"
273
+ else
274
+ "#{host}/#{path}"
275
+ end
251
276
  else
252
277
  # AWS/Google optimized for speed over correctness
253
278
  case @uploader.fog_credentials[:provider]
254
279
  when 'AWS'
255
280
  # if directory is a valid subdomain, use that style for access
256
- if @uploader.fog_directory.to_s =~ /^(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}$))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]$/
281
+ if @uploader.fog_directory.to_s =~ /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
257
282
  "https://#{@uploader.fog_directory}.s3.amazonaws.com/#{path}"
258
283
  else
259
284
  # directory is not a valid subdomain, so use path style for access
@@ -277,9 +302,9 @@ module CarrierWave
277
302
  # or
278
303
  # [NilClass] no url available
279
304
  #
280
- def url
305
+ def url(options = {})
281
306
  if !@uploader.fog_public
282
- authenticated_url
307
+ authenticated_url(options)
283
308
  else
284
309
  public_url
285
310
  end
@@ -322,7 +347,7 @@ module CarrierWave
322
347
  # [Fog::#{provider}::File] file data from remote service
323
348
  #
324
349
  def file
325
- @file ||= directory.files.get(path)
350
+ @file ||= directory.files.head(path)
326
351
  end
327
352
 
328
353
  end
@@ -48,11 +48,11 @@ module CarrierWave
48
48
  end
49
49
 
50
50
  def failure_message
51
- "expected #{@actual.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
51
+ "expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
52
52
  end
53
53
 
54
54
  def negative_failure_message
55
- "expected #{@actual.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
55
+ "expected #{@actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
56
56
  end
57
57
 
58
58
  def description
@@ -182,7 +182,7 @@ module CarrierWave
182
182
  end
183
183
  end
184
184
 
185
- def be_no_height_than(height)
185
+ def be_no_taller_than(height)
186
186
  BeNoTallerThan.new(height)
187
187
  end
188
188
 
@@ -38,6 +38,7 @@ module CarrierWave
38
38
  include CarrierWave::Uploader::Versions
39
39
  include CarrierWave::Uploader::DefaultUrl
40
40
  include CarrierWave::Uploader::Configuration
41
+ include CarrierWave::Uploader::Serialization
41
42
  end # Base
42
43
 
43
44
  end # Uploader
@@ -90,9 +90,9 @@ module CarrierWave
90
90
  ##
91
91
  # Caches the given file. Calls process! to trigger any process callbacks.
92
92
  #
93
- # By default, cache!() uses copy_to(), which operates by copying the file
94
- # to the cache, then deleting the original file. If move_to_cache() is
95
- # overriden to return true, then cache!() uses move_to(), which simply
93
+ # By default, cache!() uses copy_to(), which operates by copying the file
94
+ # to the cache, then deleting the original file. If move_to_cache() is
95
+ # overriden to return true, then cache!() uses move_to(), which simply
96
96
  # moves the file to the cache. Useful for large files.
97
97
  #
98
98
  # === Parameters
@@ -11,28 +11,6 @@ module CarrierWave
11
11
  add_config :base_path
12
12
  add_config :permissions
13
13
  add_config :storage_engines
14
- add_config :s3_access_policy
15
- add_config :s3_bucket
16
- add_config :s3_access_key_id
17
- add_config :s3_secret_access_key
18
- add_config :s3_cnamed
19
- add_config :s3_headers
20
- add_config :s3_region
21
- add_config :s3_use_ssl
22
- add_config :s3_authentication_timeout
23
- add_config :cloud_files_username
24
- add_config :cloud_files_api_key
25
- add_config :cloud_files_container
26
- add_config :cloud_files_cdn_host
27
- add_config :cloud_files_auth_url
28
- add_config :cloud_files_snet
29
- add_config :grid_fs_connection
30
- add_config :grid_fs_database
31
- add_config :grid_fs_host
32
- add_config :grid_fs_port
33
- add_config :grid_fs_username
34
- add_config :grid_fs_password
35
- add_config :grid_fs_access_url
36
14
  add_config :store_dir
37
15
  add_config :cache_dir
38
16
  add_config :enable_processing
@@ -109,7 +87,8 @@ module CarrierWave
109
87
  end
110
88
 
111
89
  def #{name}
112
- self.class.#{name}
90
+ value = self.class.#{name}
91
+ value.instance_of?(Proc) ? value.call : value
113
92
  end
114
93
  RUBY
115
94
  end
@@ -126,20 +105,9 @@ module CarrierWave
126
105
  config.permissions = 0644
127
106
  config.storage_engines = {
128
107
  :file => "CarrierWave::Storage::File",
129
- :fog => "CarrierWave::Storage::Fog",
130
- :s3 => "CarrierWave::Storage::S3",
131
- :grid_fs => "CarrierWave::Storage::GridFS",
132
- :right_s3 => "CarrierWave::Storage::RightS3",
133
- :cloud_files => "CarrierWave::Storage::CloudFiles"
108
+ :fog => "CarrierWave::Storage::Fog"
134
109
  }
135
110
  config.storage = :file
136
- config.s3_headers = {}
137
- config.s3_access_policy = :public_read
138
- config.s3_region = 'us-east-1'
139
- config.s3_authentication_timeout = 600
140
- config.grid_fs_database = 'carrierwave'
141
- config.grid_fs_host = 'localhost'
142
- config.grid_fs_port = 27017
143
111
  config.fog_attributes = {}
144
112
  config.fog_credentials = {}
145
113
  config.fog_public = true
@@ -154,7 +122,7 @@ module CarrierWave
154
122
  config.ignore_processing_errors = true
155
123
  config.validate_integrity = true
156
124
  config.validate_processing = true
157
- config.root = CarrierWave.root
125
+ config.root = lambda { CarrierWave.root }
158
126
  config.base_path = CarrierWave.base_path
159
127
  config.enable_processing = true
160
128
  config.ensure_multipart_form = true
@@ -67,7 +67,7 @@ module CarrierWave
67
67
  # [url (String)] The URL where the remote file is stored
68
68
  #
69
69
  def process_uri(uri)
70
- URI.parse(URI.escape(URI.unescape(uri)))
70
+ URI.parse(URI.escape(URI.unescape(uri)).gsub("[", "%5B").gsub("]", "%5D"))
71
71
  end
72
72
 
73
73
  end # Download
@@ -7,7 +7,7 @@ module CarrierWave
7
7
  attr_reader :model, :mounted_as
8
8
 
9
9
  ##
10
- # If a model is given as the first parameter, it will stored in the uploader, and
10
+ # If a model is given as the first parameter, it will be stored in the uploader, and
11
11
  # available throught +#model+. Likewise, mounted_as stores the name of the column
12
12
  # where this instance of the uploader is mounted. These values can then be used inside
13
13
  # your uploader.
@@ -36,4 +36,4 @@ module CarrierWave
36
36
 
37
37
  end # Mountable
38
38
  end # Uploader
39
- end # CarrierWave
39
+ end # CarrierWave
@@ -79,7 +79,9 @@ module CarrierWave
79
79
  def process!(new_file=nil)
80
80
  if enable_processing
81
81
  self.class.processors.each do |method, args, condition|
82
- next if condition && !self.send(condition, new_file)
82
+ if(condition)
83
+ next if !(condition.respond_to?(:call) ? condition.call(self, :args => args, :method => method, :file => new_file) : self.send(condition, new_file))
84
+ end
83
85
  self.send(method, *args)
84
86
  end
85
87
  end