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.
Files changed (67) hide show
  1. data/Generators +1 -1
  2. data/History.txt +39 -2
  3. data/Manifest.txt +19 -5
  4. data/README.rdoc +180 -55
  5. data/Rakefile +11 -4
  6. data/features/grid_fs_storage.feature +32 -0
  7. data/features/step_definitions/general_steps.rb +6 -1
  8. data/features/support/activerecord.rb +1 -1
  9. data/features/support/env.rb +3 -16
  10. data/lib/carrierwave.rb +19 -74
  11. data/lib/carrierwave/compatibility/paperclip.rb +2 -2
  12. data/lib/carrierwave/core_ext/inheritable_attributes.rb +3 -3
  13. data/lib/carrierwave/mount.rb +36 -27
  14. data/lib/carrierwave/orm/activerecord.rb +3 -3
  15. data/lib/carrierwave/orm/datamapper.rb +2 -2
  16. data/lib/carrierwave/orm/mongoid.rb +23 -0
  17. data/lib/carrierwave/orm/mongomapper.rb +1 -1
  18. data/lib/carrierwave/orm/sequel.rb +4 -16
  19. data/lib/carrierwave/processing/image_science.rb +54 -25
  20. data/lib/carrierwave/processing/mini_magick.rb +269 -0
  21. data/lib/carrierwave/processing/rmagick.rb +4 -6
  22. data/lib/carrierwave/sanitized_file.rb +7 -6
  23. data/lib/carrierwave/storage/abstract.rb +0 -2
  24. data/lib/carrierwave/storage/file.rb +3 -5
  25. data/lib/carrierwave/storage/grid_fs.rb +92 -0
  26. data/lib/carrierwave/storage/right_s3.rb +183 -0
  27. data/lib/carrierwave/storage/s3.rb +37 -69
  28. data/lib/carrierwave/test/matchers.rb +22 -8
  29. data/lib/carrierwave/uploader.rb +2 -2
  30. data/lib/carrierwave/uploader/cache.rb +21 -18
  31. data/lib/carrierwave/uploader/configuration.rb +122 -0
  32. data/lib/carrierwave/uploader/default_url.rb +19 -0
  33. data/lib/carrierwave/uploader/processing.rb +4 -2
  34. data/lib/carrierwave/uploader/remove.rb +0 -1
  35. data/lib/carrierwave/uploader/store.rb +1 -68
  36. data/lib/carrierwave/uploader/url.rb +1 -1
  37. data/lib/carrierwave/uploader/versions.rb +3 -4
  38. data/{lib/generators → merb_generators}/uploader_generator.rb +0 -0
  39. data/rails_generators/uploader/templates/uploader.rb +4 -4
  40. data/spec/compatibility/paperclip_spec.rb +11 -2
  41. data/spec/fixtures/landscape.jpg +0 -0
  42. data/spec/fixtures/portrait.jpg +0 -0
  43. data/spec/mount_spec.rb +0 -25
  44. data/spec/orm/datamapper_spec.rb +55 -48
  45. data/spec/orm/mongoid_spec.rb +206 -0
  46. data/spec/orm/mongomapper_spec.rb +19 -1
  47. data/spec/orm/sequel_spec.rb +3 -12
  48. data/spec/processing/image_science_spec.rb +56 -0
  49. data/spec/processing/mini_magick_spec.rb +76 -0
  50. data/spec/processing/rmagick_spec.rb +68 -0
  51. data/spec/sanitized_file_spec.rb +84 -74
  52. data/spec/spec_helper.rb +1 -3
  53. data/spec/storage/grid_fs_spec.rb +78 -0
  54. data/spec/storage/right_s3_spec.rb +75 -0
  55. data/spec/storage/s3_spec.rb +83 -0
  56. data/spec/uploader/cache_spec.rb +1 -13
  57. data/spec/uploader/configuration_spec.rb +105 -0
  58. data/spec/uploader/{default_path_spec.rb → default_url_spec.rb} +22 -5
  59. data/spec/uploader/paths_spec.rb +1 -1
  60. data/spec/uploader/processing_spec.rb +11 -0
  61. data/spec/uploader/store_spec.rb +21 -47
  62. data/spec/uploader/versions_spec.rb +0 -8
  63. metadata +105 -17
  64. data/LICENSE +0 -8
  65. data/carrierwave.gemspec +0 -57
  66. data/lib/carrierwave/uploader/default_path.rb +0 -23
  67. 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
- require 'RMagick'
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 #{@actual_height} by #{@actual_width}."
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
- require 'RMagick'
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 #{@actual_height} by #{@actual_width}."
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
@@ -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
- if CarrierWave.config[:cache_to_cache_dir]
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), public)
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
- self.class.processors.each do |method, args|
75
- self.send(method, *args)
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
 
@@ -11,7 +11,6 @@ module CarrierWave
11
11
  #
12
12
  def remove!
13
13
  with_callbacks(:remove) do
14
- CarrierWave.logger.info 'CarrierWave: removing file'
15
14
  @file.delete if @file
16
15
  @file = nil
17
16
  @cache_id = nil
@@ -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.
@@ -13,7 +13,7 @@ module CarrierWave
13
13
  if file.respond_to?(:url) and not file.url.blank?
14
14
  file.url
15
15
  elsif current_path
16
- File.expand_path(current_path).gsub(File.expand_path(public), '')
16
+ File.expand_path(current_path).gsub(File.expand_path(root), '')
17
17
  end
18
18
  end
19
19
 
@@ -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 do |name, v|
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)
@@ -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 path as a default if there hasn't been a file uploaded
20
- # def default_path
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