carrierwave 0.4.1 → 0.4.2

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.

@@ -0,0 +1,183 @@
1
+ # encoding: utf-8
2
+ require 'right_aws'
3
+
4
+ module CarrierWave
5
+ module Storage
6
+
7
+ ##
8
+ # Uploads things to Amazon S3 webservices using the RightAWS libraries (right_aws gem).
9
+ # In order for CarrierWave to connect to Amazon S3, you'll need to specify an access key id, secret key
10
+ # and bucket
11
+ #
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
17
+ #
18
+ # The RightAWS::S3Interface is used directly as opposed to the normal RightAWS::S3::Bucket et.al. classes.
19
+ # This gives much improved performance and avoids unnecessary requests.
20
+ #
21
+ # You can set the access policy for the uploaded files:
22
+ #
23
+ # CarrierWave.configure do |config|
24
+ # config.s3_access_policy = 'public-read'
25
+ # end
26
+ #
27
+ # The default is 'public-read'. For more options see:
28
+ #
29
+ # http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html#RESTCannedAccessPolicies
30
+ #
31
+ # You can change the generated url to a cnamed domain by setting the cnamed config:
32
+ #
33
+ # CarrierWave.configure do |config|
34
+ # config.s3_cnamed = true
35
+ # config.s3_bucket = 'bucketname.domain.tld'
36
+ # end
37
+ #
38
+ # Now the resulting url will be
39
+ #
40
+ # http://bucketname.domain.tld/path/to/file
41
+ #
42
+ # instead of
43
+ #
44
+ # http://bucketname.domain.tld.s3.amazonaws.com/path/to/file
45
+ #
46
+ class RightS3 < Abstract
47
+
48
+ class File
49
+
50
+ def initialize(uploader, base, path)
51
+ @uploader = uploader
52
+ @path = path
53
+ @base = base
54
+ end
55
+
56
+ ##
57
+ # Returns the current path of the file on S3
58
+ #
59
+ # === Returns
60
+ #
61
+ # [String] A path
62
+ #
63
+ def path
64
+ @path
65
+ end
66
+
67
+ ##
68
+ # Reads the contents of the file from S3
69
+ #
70
+ # === Returns
71
+ #
72
+ # [String] contents of the file
73
+ #
74
+ def read
75
+ result = connection.get(bucket, @path)
76
+ headers["content-type"] = result[:headers]["content-type"]
77
+ result[:object]
78
+ end
79
+
80
+ ##
81
+ # Remove the file from Amazon S3
82
+ #
83
+ def delete
84
+ connection.delete(bucket, @path)
85
+ end
86
+
87
+ ##
88
+ # Returns the url on Amazon's S3 service
89
+ #
90
+ # === Returns
91
+ #
92
+ # [String] file's url
93
+ #
94
+ def url
95
+ if @uploader.s3_cnamed
96
+ ["http://", @uploader.s3_bucket, @path].compact.join('/')
97
+ else
98
+ ["http://#{@uploader.s3_bucket}.s3.amazonaws.com", @path].compact.join('/')
99
+ end
100
+ end
101
+
102
+ #def about
103
+ # s3_object.about
104
+ #end
105
+
106
+ #def metadata
107
+ # s3_object.metadata
108
+ #end
109
+
110
+ def content_type
111
+ headers["content-type"]
112
+ end
113
+
114
+ def content_type=(new_content_type)
115
+ headers["content-type"] = new_content_type
116
+ end
117
+
118
+ #def content_disposition
119
+ # s3_object.content_disposition
120
+ #end
121
+
122
+ #def content_disposition=(new_disposition)
123
+ # s3_object.content_disposition = new_disposition
124
+ #end
125
+
126
+ def store(data)
127
+ connection.put(bucket, @path, data, headers)
128
+ end
129
+
130
+ private
131
+
132
+ def headers
133
+ @headers ||= { 'x-amz-acl' => @uploader.s3_access_policy }
134
+ end
135
+
136
+ def bucket
137
+ @uploader.s3_bucket
138
+ end
139
+
140
+ def connection
141
+ @base.connection
142
+ end
143
+
144
+ end
145
+
146
+ ##
147
+ # Store the file on S3
148
+ #
149
+ # === Parameters
150
+ #
151
+ # [file (CarrierWave::SanitizedFile)] the file to store
152
+ #
153
+ # === Returns
154
+ #
155
+ # [CarrierWave::Storage::RightS3::File] the stored file
156
+ #
157
+ def store!(file)
158
+ f = CarrierWave::Storage::RightS3::File.new(uploader, self, uploader.store_path)
159
+ f.store(file.read)
160
+ f
161
+ end
162
+
163
+ # Do something to retrieve the file
164
+ #
165
+ # @param [String] identifier uniquely identifies the file
166
+ #
167
+ # [identifier (String)] uniquely identifies the file
168
+ #
169
+ # === Returns
170
+ #
171
+ # [CarrierWave::Storage::RightS3::File] the stored file
172
+ #
173
+ def retrieve!(identifier)
174
+ CarrierWave::Storage::RightS3::File.new(uploader, self, uploader.store_path(identifier))
175
+ end
176
+
177
+ def connection
178
+ @connection ||= RightAws::S3Interface.new(uploader.s3_access_key_id, uploader.s3_secret_access_key)
179
+ end
180
+
181
+ end # RightS3
182
+ end # Storage
183
+ end # CarrierWave
@@ -6,7 +6,8 @@ module CarrierWave
6
6
  add_config :root
7
7
  add_config :permissions
8
8
  add_config :storage_engines
9
- add_config :s3_access
9
+ add_config :s3_access # for aws/s3
10
+ add_config :s3_access_policy # for right_aws
10
11
  add_config :s3_bucket
11
12
  add_config :s3_access_key_id
12
13
  add_config :s3_secret_access_key
@@ -16,6 +17,7 @@ module CarrierWave
16
17
  add_config :grid_fs_access_url
17
18
  add_config :store_dir
18
19
  add_config :cache_dir
20
+ add_config :enable_processing
19
21
 
20
22
  # Mounting
21
23
  add_config :ignore_integrity_errors
@@ -29,10 +31,12 @@ module CarrierWave
29
31
  config.storage_engines = {
30
32
  :file => "CarrierWave::Storage::File",
31
33
  :s3 => "CarrierWave::Storage::S3",
32
- :grid_fs => "CarrierWave::Storage::GridFS"
34
+ :grid_fs => "CarrierWave::Storage::GridFS",
35
+ :right_s3 => "CarrierWave::Storage::RightS3"
33
36
  }
34
37
  config.storage = :file
35
38
  config.s3_access = :public_read
39
+ config.s3_access_policy = 'public-read'
36
40
  config.grid_fs_database = 'carrierwave'
37
41
  config.grid_fs_host = 'localhost'
38
42
  config.store_dir = 'uploads'
@@ -42,6 +46,7 @@ module CarrierWave
42
46
  config.validate_integrity = true
43
47
  config.validate_processing = true
44
48
  config.root = CarrierWave.root
49
+ config.enable_processing = true
45
50
  end
46
51
  end
47
52
 
@@ -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
 
@@ -2,47 +2,54 @@
2
2
 
3
3
  require File.dirname(__FILE__) + '/../spec_helper'
4
4
 
5
+ require 'dm-core'
6
+ require 'dm-validations'
5
7
  require 'carrierwave/orm/datamapper'
6
8
 
7
9
  DataMapper.setup(:default, 'sqlite3::memory:')
8
10
 
9
11
  describe CarrierWave::DataMapper do
10
-
12
+
11
13
  before do
12
14
  uploader = Class.new(CarrierWave::Uploader::Base)
13
-
15
+
14
16
  @class = Class.new
15
17
  @class.class_eval do
16
18
  include DataMapper::Resource
17
19
 
18
20
  storage_names[:default] = 'events'
19
-
21
+
20
22
  property :id, DataMapper::Types::Serial
21
- property :image, String
22
-
23
+
24
+ # auto validation off currently for inferred type
25
+ # validation. issue is that validations are done on
26
+ # the value returned by model#property_name which is overloaded
27
+ # by carrierwave. pull request in @dm-more to remedy this.
28
+ property :image, String, :auto_validation => false
29
+
23
30
  mount_uploader :image, uploader
24
31
  end
25
-
32
+
26
33
  @class.auto_migrate!
27
-
34
+
28
35
  @uploader = uploader
29
-
36
+
30
37
  @event = @class.new
31
38
  end
32
-
39
+
33
40
  describe '#image' do
34
-
41
+
35
42
  it "should return blank uploader when nothing has been assigned" do
36
43
  @event.image.should be_blank
37
44
  end
38
-
45
+
39
46
  it "should return blank uploader when an empty string has been assigned" do
40
47
  repository(:default).adapter.query("INSERT INTO events (image) VALUES ('')")
41
48
  @event = @class.first
42
-
49
+
43
50
  @event.image.should be_blank
44
51
  end
45
-
52
+
46
53
  it "should retrieve a file from the storage if a value is stored in the database" do
47
54
  repository(:default).adapter.query("INSERT INTO events (image) VALUES ('test.jpg')")
48
55
  @event = @class.first
@@ -51,82 +58,64 @@ describe CarrierWave::DataMapper do
51
58
  @event.reload
52
59
  @event.image.should be_an_instance_of(@uploader)
53
60
  end
54
-
61
+
55
62
  it "should set the path to the store dir" do
56
63
  @event.attribute_set(:image, 'test.jpeg')
57
64
  @event.save
58
65
  @event.reload
59
66
  @event.image.current_path.should == public_path('uploads/test.jpeg')
60
67
  end
61
-
68
+
62
69
  end
63
-
70
+
64
71
  describe '#image=' do
65
-
72
+
66
73
  it "should cache a file" do
67
74
  @event.image = stub_file('test.jpeg')
68
75
  @event.image.should be_an_instance_of(@uploader)
69
76
  end
70
-
77
+
71
78
  it "should write nothing to the database, to prevent overriden filenames to fail because of unassigned attributes" do
72
79
  @event.attribute_get(:image).should be_nil
73
80
  end
74
-
81
+
75
82
  it "should copy a file into into the cache directory" do
76
83
  @event.image = stub_file('test.jpeg')
77
84
  @event.image.current_path.should =~ /^#{public_path('uploads/tmp')}/
78
85
  end
79
-
86
+
80
87
  it "should do nothing when nil is assigned" do
81
88
  @event.image = nil
82
89
  @event.image.should be_blank
83
90
  end
84
-
91
+
85
92
  it "should do nothing when an empty string is assigned" do
86
93
  @event.image = ''
87
94
  @event.image.should be_blank
88
95
  end
89
-
96
+
90
97
  end
91
-
98
+
92
99
  describe '#save' do
93
-
100
+
94
101
  it "should do nothing when no file has been assigned" do
95
102
  @event.save
96
103
  @event.image.should be_blank
97
104
  end
98
-
105
+
99
106
  it "should copy the file to the upload directory when a file has been assigned" do
100
107
  @event.image = stub_file('test.jpeg')
101
108
  @event.save
102
109
  @event.image.should be_an_instance_of(@uploader)
103
110
  @event.image.current_path.should == public_path('uploads/test.jpeg')
104
111
  end
105
-
106
- # it "should do nothing when a validation fails" do
107
- # pending "how do we test with and without dm-validations?"
108
- # @class.validate { |r| r.errors.add :textfile, "FAIL!" }
109
- # @event.image = stub_file('test.jpeg')
110
- # @event.save
111
- # @event.image.should be_an_instance_of(@uploader)
112
- # @event.image.current_path.should =~ /^#{public_path('uploads/tmp')}/
113
- # end
114
-
112
+
115
113
  it "should assign the filename to the database" do
116
114
  @event.image = stub_file('test.jpeg')
117
115
  @event.save
118
116
  @event.reload
119
117
  @event.attribute_get(:image).should == 'test.jpeg'
120
118
  end
121
-
122
- # it "should assign the filename before validation" do
123
- # pending "how do we test with and without dm-validations?"
124
- # @class.validate { |r| r.errors.add_to_base "FAIL!" if r[:image].nil? }
125
- # @event.image = stub_file('test.jpeg')
126
- # @event.save
127
- # @event.reload
128
- # @event.attribute_get(:image).should == 'test.jpeg'
129
- # end
130
119
 
131
120
  it "should remove the image if remove_image? returns true" do
132
121
  @event.image = stub_file('test.jpeg')
@@ -138,14 +127,32 @@ describe CarrierWave::DataMapper do
138
127
  @event.attribute_get(:image).should == ''
139
128
  end
140
129
 
130
+ describe "with validations" do
131
+ it "should do nothing when a validation fails" do
132
+ @class.validates_with_block(:textfile) { [false, "FAIL!"] }
133
+ @event.image = stub_file('test.jpeg')
134
+ @event.save
135
+ @event.image.should be_an_instance_of(@uploader)
136
+ @event.image.current_path.should =~ /^#{public_path('uploads/tmp')}/
137
+ end
138
+
139
+ it "should assign the filename before validation" do
140
+ @class.validates_with_block(:image) { [false, "FAIL!"] if self.image.nil? }
141
+ @event.image = stub_file('test.jpeg')
142
+ @event.save
143
+ @event.reload
144
+ @event.attribute_get(:image).should == 'test.jpeg'
145
+ end
146
+ end
147
+
141
148
  end
142
149
 
143
150
  describe '#destroy' do
144
-
151
+
145
152
  it "should do nothing when no file has been assigned" do
146
153
  @event.destroy
147
154
  end
148
-
155
+
149
156
  it "should remove the file from the filesystem" do
150
157
  @event.image = stub_file('test.jpeg')
151
158
  @event.save.should be_true
@@ -157,5 +164,5 @@ describe CarrierWave::DataMapper do
157
164
  end
158
165
 
159
166
  end
160
-
167
+
161
168
  end
@@ -0,0 +1,204 @@
1
+ # encoding: utf-8
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ require 'carrierwave/orm/mongoid'
5
+
6
+ Mongoid.connect_to("carrierwave_test")
7
+
8
+ describe CarrierWave::Mongoid do
9
+
10
+ before do
11
+ uploader = Class.new(CarrierWave::Uploader::Base)
12
+
13
+ @class = Mongoid::Document
14
+ @class.class_eval do
15
+ mount_uploader :image, uploader
16
+ end
17
+
18
+ @uploader = uploader
19
+ end
20
+
21
+ after do
22
+ @class.collection.drop
23
+ end
24
+
25
+ describe '#image' do
26
+
27
+ context "when nothing is assigned" do
28
+
29
+ before do
30
+ @document = @class.new
31
+ end
32
+
33
+ it "returns a blank uploader" do
34
+ @document.image.should be_blank
35
+ end
36
+
37
+ end
38
+
39
+ context "when an empty string is assigned" do
40
+
41
+ before do
42
+ @document = @class.new(:image_filename => "")
43
+ @document.save
44
+ end
45
+
46
+ it "returns a blank uploader" do
47
+ @saved_doc = @class.find(:first)
48
+ @saved_doc.image.should be_blank
49
+ end
50
+
51
+ end
52
+
53
+ context "when a filename is saved in the database" do
54
+
55
+ before do
56
+ @document = @class.new(:image_filename => "test.jpg")
57
+ @document.save
58
+ @doc = @class.find(:first)
59
+ end
60
+
61
+ it "returns an uploader" do
62
+ @doc.image.should be_an_instance_of(@uploader)
63
+ end
64
+
65
+ it "sets the path to the store directory" do
66
+ @doc.image.current_path.should == public_path('uploads/test.jpg')
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ describe '#image=' do
74
+
75
+ before do
76
+ @doc = @class.new
77
+ end
78
+
79
+ context "when nil is assigned" do
80
+
81
+ it "does not set the value" do
82
+ @doc.image = nil
83
+ @doc.image.should be_blank
84
+ end
85
+
86
+ end
87
+
88
+ context "when an empty string is assigned" do
89
+
90
+ it "does not set the value" do
91
+ @doc.image = ''
92
+ @doc.image.should be_blank
93
+ end
94
+
95
+ end
96
+
97
+ context "when a file is assigned" do
98
+
99
+ it "should cache a file" do
100
+ @doc.image = stub_file('test.jpeg')
101
+ @doc.image.should be_an_instance_of(@uploader)
102
+ end
103
+
104
+ it "should write nothing to the database, to prevent overriden filenames to fail because of unassigned attributes" do
105
+ @doc.image_filename.should be_nil
106
+ end
107
+
108
+ it "should copy a file into into the cache directory" do
109
+ @doc.image = stub_file('test.jpeg')
110
+ @doc.image.current_path.should =~ /^#{public_path('uploads\/tmp')}/
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ describe "#save" do
118
+
119
+ before do
120
+ @doc = @class.new
121
+ end
122
+
123
+ context "when no file is assigned" do
124
+
125
+ it "image is blank" do
126
+ @doc.save
127
+ @doc.image.should be_blank
128
+ end
129
+
130
+ end
131
+
132
+ context "when a file is assigned" do
133
+
134
+ it "copies the file to the upload directory" do
135
+ @doc.image = stub_file('test.jpg')
136
+ @doc.save
137
+ @doc.image.should be_an_instance_of(@uploader)
138
+ @doc.image.current_path.should == public_path('uploads/test.jpg')
139
+ end
140
+
141
+ it "saves the filename in the database" do
142
+ @doc.image = stub_file('test.jpg')
143
+ @doc.save
144
+ @doc.image_filename.should == 'test.jpg'
145
+ end
146
+
147
+ context "when remove_image? is true" do
148
+
149
+ it "removes the image" do
150
+ @doc.image = stub_file('test.jpeg')
151
+ @doc.save
152
+ @doc.remove_image = true
153
+ @doc.save
154
+ @doc.image.should be_blank
155
+ @doc.image_filename.should == ''
156
+ end
157
+
158
+ end
159
+
160
+ end
161
+
162
+ end
163
+
164
+ describe '#destroy' do
165
+
166
+ before do
167
+ @doc = @class.new
168
+ end
169
+
170
+ describe "when file assigned" do
171
+
172
+ it "removes the file from the filesystem" do
173
+ @doc.image = stub_file('test.jpeg')
174
+ @doc.save.should be_true
175
+ File.exist?(public_path('uploads/test.jpeg')).should be_true
176
+ @doc.image.should be_an_instance_of(@uploader)
177
+ @doc.image.current_path.should == public_path('uploads/test.jpeg')
178
+ @doc.destroy
179
+ File.exist?(public_path('uploads/test.jpeg')).should be_false
180
+ end
181
+
182
+ end
183
+
184
+ describe "when file is not assigned" do
185
+
186
+ it "deletes the instance of @class after save" do
187
+ @doc.save
188
+ @class.count(:all, {}).should eql(1)
189
+ @doc.destroy
190
+ end
191
+
192
+ it "deletes the instance of @class after save and then re-looking up the instance" do
193
+ @doc.save
194
+ @class.count(:all, {}).should eql(1)
195
+ @doc = @class.first
196
+ @doc.destroy
197
+ end
198
+
199
+ end
200
+
201
+ end
202
+
203
+
204
+ end