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
@@ -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,10 +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
40
38
  use CarrierWave::Uploader::DefaultUrl
39
+ use CarrierWave::Uploader::Configuration
41
40
  end # Base
42
41
 
43
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,59 @@
1
+ module CarrierWave
2
+
3
+ module Uploader
4
+ module Configuration
5
+
6
+ setup do
7
+ add_config :root
8
+ add_config :permissions
9
+ add_config :storage_engines
10
+ add_config :s3_access
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_access_url
18
+ add_config :store_dir
19
+ add_config :cache_dir
20
+
21
+ # Mounting
22
+ add_config :ignore_integrity_errors
23
+ add_config :ignore_processing_errors
24
+ add_config :validate_integrity
25
+ add_config :validate_processing
26
+ add_config :mount_on
27
+ end
28
+
29
+ module ClassMethods
30
+
31
+ def add_config(name)
32
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
33
+ def self.#{name}(value=nil)
34
+ @#{name} = value if value
35
+ return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
36
+ name = superclass.#{name}
37
+ return nil if name.nil? && !#{self}.instance_variable_defined?("@#{name}")
38
+ @#{name} = name && !name.is_a?(Module) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
39
+ end
40
+
41
+ def self.#{name}=(value)
42
+ @#{name} = value
43
+ end
44
+
45
+ def #{name}
46
+ self.class.#{name}
47
+ end
48
+ RUBY
49
+ end
50
+
51
+ def configure
52
+ yield self
53
+ end
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+
@@ -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,8 +4,8 @@ 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
11
  module ClassMethods
@@ -14,7 +14,7 @@ module CarrierWave
14
14
  # Sets the storage engine to be used when storing files with this uploader.
15
15
  # Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
16
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
17
+ # be added to CarrierWave::Uploader::Base.storage_engines so they can be referred
18
18
  # to by a symbol, which should be more convenient
19
19
  #
20
20
  # If no argument is given, it will simply return the currently used storage engine.
@@ -35,31 +35,17 @@ module CarrierWave
35
35
  #
36
36
  def storage(storage = nil)
37
37
  if storage.is_a?(Symbol)
38
- @storage = get_storage_by_symbol(storage)
39
- @storage.setup!
38
+ @storage = eval(storage_engines[storage])
40
39
  elsif storage
41
40
  @storage = storage
42
- @storage.setup!
43
41
  elsif @storage.nil?
44
42
  # Get the storage from the superclass if there is one
45
43
  @storage = superclass.storage rescue nil
46
44
  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
45
  return @storage
53
46
  end
54
-
55
47
  alias_method :storage=, :storage
56
48
 
57
- private
58
-
59
- def get_storage_by_symbol(symbol)
60
- eval(CarrierWave.config[:storage_engines][symbol])
61
- end
62
-
63
49
  end
64
50
 
65
51
  ##
@@ -80,19 +66,6 @@ module CarrierWave
80
66
  @filename
81
67
  end
82
68
 
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
69
  ##
97
70
  # Calculates the path where the file should be stored. If +for_file+ is given, it will be
98
71
  # 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
 
@@ -128,10 +128,7 @@ module CarrierWave
128
128
  end
129
129
 
130
130
  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
131
+ versions.each { |name, v| v.remove! }
135
132
  end
136
133
 
137
134
  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.
@@ -4,6 +4,15 @@ require File.dirname(__FILE__) + '/../spec_helper'
4
4
 
5
5
  require 'carrierwave/orm/activerecord'
6
6
 
7
+ module Rails
8
+ def self.root
9
+ File.expand_path(File.join('..'), File.dirname(__FILE__))
10
+ end
11
+ def self.env
12
+ "test"
13
+ end
14
+ end unless defined?(Rails)
15
+
7
16
  describe CarrierWave::Compatibility::Paperclip do
8
17
 
9
18
  before do
@@ -21,12 +30,12 @@ describe CarrierWave::Compatibility::Paperclip do
21
30
 
22
31
  describe '#store_path' do
23
32
  it "should mimics paperclip default" do
24
- @uploader.store_path("monkey.png").should == CarrierWave.config[:root] + "/public/system/monkeys/23/original/monkey.png"
33
+ @uploader.store_path("monkey.png").should == CarrierWave::Uploader::Base.root + "/system/monkeys/23/original/monkey.png"
25
34
  end
26
35
 
27
36
  it "should interpolate the root path" do
28
37
  @uploader.stub!(:paperclip_path).and_return(":rails_root/foo/bar")
29
- @uploader.store_path("monkey.png").should == CarrierWave.config[:root] + "/foo/bar"
38
+ @uploader.store_path("monkey.png").should == Rails.root + "/foo/bar"
30
39
  end
31
40
 
32
41
  it "should interpolate the attachment" do
@@ -31,7 +31,6 @@ describe CarrierWave::Mount do
31
31
  end
32
32
  end
33
33
 
34
- @instance.image_uploader.should be_an_instance_of(@uploader)
35
34
  @instance.image = stub_file('test.jpg')
36
35
  @instance.image.should be_an_instance_of(@uploader)
37
36
  end
@@ -39,34 +38,10 @@ describe CarrierWave::Mount do
39
38
  it "should inherit uploaders to subclasses" do
40
39
  @subclass = Class.new(@class)
41
40
  @subclass_instance = @subclass.new
42
- @subclass_instance.image_uploader.should be_an_instance_of(@uploader)
43
41
  @subclass_instance.image = stub_file('test.jpg')
44
42
  @subclass_instance.image.should be_an_instance_of(@uploader)
45
43
  end
46
44
 
47
- describe '#image_uploader' do
48
- it "should return the uploader" do
49
- @instance.image_uploader.should be_an_instance_of(@uploader)
50
- end
51
- end
52
-
53
- describe '#image_uploader=' do
54
- it "should set the uploader" do
55
- @my_uploader = @uploader.new
56
- @instance.image_uploader = @my_uploader
57
- @instance.image_uploader.should == @my_uploader
58
- end
59
-
60
- it "should use the set uploader" do
61
- @my_uploader = @uploader.new
62
- @my_uploader.store!(stub_file('test.jpg'))
63
- @instance.image_uploader = @my_uploader
64
- @instance.image_uploader.should == @my_uploader
65
- @instance.image.should == @my_uploader
66
- @instance.image.current_path.should == public_path('uploads/test.jpg')
67
- end
68
- end
69
-
70
45
  describe '#image' do
71
46
 
72
47
  it "should return a blank uploader when nothing has been assigned" do
@@ -17,7 +17,7 @@ describe CarrierWave::DataMapper do
17
17
 
18
18
  storage_names[:default] = 'events'
19
19
 
20
- property :id, Integer, :key => true
20
+ property :id, DataMapper::Types::Serial
21
21
  property :image, String
22
22
 
23
23
  mount_uploader :image, uploader
@@ -21,7 +21,6 @@ require 'spec/autorun'
21
21
  require 'carrierwave'
22
22
 
23
23
  require 'logger'
24
- CarrierWave.logger = Logger.new(nil)
25
24
 
26
25
  alias :running :lambda
27
26
 
@@ -33,8 +32,9 @@ def public_path( *paths )
33
32
  File.expand_path(File.join(File.dirname(__FILE__), 'public', *paths))
34
33
  end
35
34
 
36
- CarrierWave.config[:public] = public_path
37
- CarrierWave.config[:root] = File.expand_path(File.dirname(__FILE__))
35
+ CarrierWave.configure do |config|
36
+ config.root = public_path
37
+ end
38
38
 
39
39
  module CarrierWave
40
40
  module Test
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe CarrierWave::Storage::GridFS do
6
+
7
+ before do
8
+ @database = Mongo::Connection.new('localhost').db('carrierwave_test')
9
+ @uploader = mock('an uploader')
10
+ @uploader.stub!(:grid_fs_database).and_return("carrierwave_test")
11
+ @uploader.stub!(:grid_fs_host).and_return("localhost")
12
+ @uploader.stub!(:grid_fs_access_url).and_return(nil)
13
+
14
+ @storage = CarrierWave::Storage::GridFS.new(@uploader)
15
+ @file = CarrierWave::SanitizedFile.new(file_path('test.jpg'))
16
+ end
17
+
18
+ after do
19
+ GridFS::GridStore.unlink(@database, 'uploads/bar.txt')
20
+ end
21
+
22
+ describe '#store!' do
23
+ before do
24
+ @uploader.stub!(:store_path).and_return('uploads/bar.txt')
25
+ @grid_fs_file = @storage.store!(@file)
26
+ end
27
+
28
+ it "should upload the file to gridfs" do
29
+ GridFS::GridStore.read(@database, 'uploads/bar.txt').should == 'this is stuff'
30
+ end
31
+
32
+ it "should not have a path" do
33
+ @grid_fs_file.path.should be_nil
34
+ end
35
+
36
+ it "should not have a URL" do
37
+ @grid_fs_file.url.should be_nil
38
+ end
39
+
40
+ it "should be deletable" do
41
+ @grid_fs_file.delete
42
+ GridFS::GridStore.read(@database, 'uploads/bar.txt').should == ''
43
+ end
44
+ end
45
+
46
+ describe '#retrieve!' do
47
+ before do
48
+ GridFS::GridStore.open(@database, 'uploads/bar.txt', 'w') { |f| f.puts "A test, 1234" }
49
+ @uploader.stub!(:store_path).with('bar.txt').and_return('uploads/bar.txt')
50
+ @grid_fs_file = @storage.retrieve!('bar.txt')
51
+ end
52
+
53
+ it "should retrieve the file contents from gridfs" do
54
+ @grid_fs_file.read.chomp.should == "A test, 1234"
55
+ end
56
+
57
+ it "should not have a path" do
58
+ @grid_fs_file.path.should be_nil
59
+ end
60
+
61
+ it "should not have a URL unless set" do
62
+ @grid_fs_file.url.should be_nil
63
+ end
64
+
65
+ it "should return a URL if configured" do
66
+ @uploader.stub!(:grid_fs_access_url).and_return("/image/show")
67
+ @grid_fs_file.url.should == "/image/show/uploads/bar.txt"
68
+ end
69
+
70
+ it "should be deletable" do
71
+ @grid_fs_file.delete
72
+ GridFS::GridStore.read(@database, 'uploads/bar.txt').should == ''
73
+ end
74
+ end
75
+
76
+ end