durran-carrierwave 0.3.2.3 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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