carrierwave 0.1 → 0.2.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.
- data/LICENSE +1 -1
- data/{README.md → README.rdoc} +73 -78
- data/Rakefile +12 -6
- data/lib/carrierwave.rb +33 -17
- data/lib/carrierwave/mount.rb +133 -54
- data/lib/carrierwave/orm/activerecord.rb +53 -2
- data/lib/carrierwave/orm/datamapper.rb +7 -2
- data/lib/carrierwave/orm/sequel.rb +23 -0
- data/lib/carrierwave/processing/image_science.rb +3 -3
- data/lib/carrierwave/processing/rmagick.rb +103 -47
- data/lib/carrierwave/sanitized_file.rb +74 -48
- data/lib/carrierwave/storage/abstract.rb +24 -9
- data/lib/carrierwave/storage/file.rb +23 -9
- data/lib/carrierwave/storage/s3.rb +67 -16
- data/lib/carrierwave/test/matchers.rb +112 -0
- data/lib/carrierwave/uploader.rb +264 -113
- data/lib/generators/uploader_generator.rb +7 -7
- data/rails_generators/uploader/templates/uploader.rb +9 -1
- data/spec/mount_spec.rb +147 -3
- data/spec/orm/activerecord_spec.rb +24 -3
- data/spec/orm/datamapper_spec.rb +3 -3
- data/spec/orm/sequel_spec.rb +170 -0
- data/spec/sanitized_file_spec.rb +22 -36
- data/spec/spec_helper.rb +44 -80
- data/spec/uploader_spec.rb +107 -22
- metadata +8 -4
@@ -1,20 +1,20 @@
|
|
1
1
|
module Merb
|
2
2
|
module Generators
|
3
3
|
class UploaderGenerator < NamedGenerator
|
4
|
-
|
4
|
+
|
5
5
|
def self.source_root
|
6
6
|
File.join(File.dirname(__FILE__), '..', '..', 'rails_generators', 'uploader', 'templates')
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
first_argument :name, :required => true, :desc => "The name of this uploader"
|
10
|
-
|
10
|
+
|
11
11
|
template :uploader do |t|
|
12
12
|
t.source = 'uploader.rb'
|
13
|
-
t.destination = "app/
|
13
|
+
t.destination = "app/models/#{file_name}_uploader.rb"
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
add :uploader, UploaderGenerator
|
18
|
-
|
18
|
+
|
19
19
|
end
|
20
|
-
end
|
20
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
class <%= class_name %>Uploader
|
1
|
+
class <%= class_name %>Uploader
|
2
|
+
|
3
|
+
include CarrierWave::Uploader
|
2
4
|
|
3
5
|
# Include RMagick or ImageScience support
|
4
6
|
# include CarrierWave::RMagick
|
@@ -20,6 +22,12 @@ class <%= class_name %>Uploader < CarrierWave::Uploader
|
|
20
22
|
# process :scale => [50, 50]
|
21
23
|
# end
|
22
24
|
|
25
|
+
# Add a white list of extensions which are allowed to be uploaded,
|
26
|
+
# for images you might use something like this:
|
27
|
+
# def extension_white_list
|
28
|
+
# %w(jpg jpeg gif png)
|
29
|
+
# end
|
30
|
+
|
23
31
|
# Override the filename of the uploaded files
|
24
32
|
# def filename
|
25
33
|
# "something.jpg"
|
data/spec/mount_spec.rb
CHANGED
@@ -2,8 +2,6 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
2
2
|
|
3
3
|
describe CarrierWave::Mount do
|
4
4
|
|
5
|
-
include SanitizedFileSpecHelper
|
6
|
-
|
7
5
|
after do
|
8
6
|
FileUtils.rm_rf(public_path)
|
9
7
|
end
|
@@ -14,12 +12,37 @@ describe CarrierWave::Mount do
|
|
14
12
|
@class = Class.new
|
15
13
|
@class.send(:extend, CarrierWave::Mount)
|
16
14
|
|
17
|
-
@uploader = Class.new
|
15
|
+
@uploader = Class.new do
|
16
|
+
include CarrierWave::Uploader
|
17
|
+
end
|
18
18
|
|
19
19
|
@class.mount_uploader(:image, @uploader)
|
20
20
|
@instance = @class.new
|
21
21
|
end
|
22
22
|
|
23
|
+
describe '#image_uploader' do
|
24
|
+
it "should return the uploader" do
|
25
|
+
@instance.image_uploader.should be_an_instance_of(@uploader)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#image_uploader=' do
|
30
|
+
it "should set the uploader" do
|
31
|
+
@my_uploader = @uploader.new
|
32
|
+
@instance.image_uploader = @my_uploader
|
33
|
+
@instance.image_uploader.should == @my_uploader
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should use the set uploader" do
|
37
|
+
@my_uploader = @uploader.new
|
38
|
+
@my_uploader.store!(stub_file('test.jpg'))
|
39
|
+
@instance.image_uploader = @my_uploader
|
40
|
+
@instance.image_uploader.should == @my_uploader
|
41
|
+
@instance.image.should == @my_uploader
|
42
|
+
@instance.image.current_path.should == public_path('uploads/test.jpg')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
23
46
|
describe '#image' do
|
24
47
|
|
25
48
|
it "should return nil when nothing has been assigned" do
|
@@ -66,6 +89,26 @@ describe CarrierWave::Mount do
|
|
66
89
|
@instance.image = ''
|
67
90
|
end
|
68
91
|
|
92
|
+
it "should fail silently if the image fails an integrity check" do
|
93
|
+
@uploader.class_eval do
|
94
|
+
def extension_white_list
|
95
|
+
%(txt)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
@instance.image = stub_file('test.jpg')
|
99
|
+
@instance.image.should be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should fail silently if the image fails to be processed" do
|
103
|
+
@uploader.class_eval do
|
104
|
+
process :monkey
|
105
|
+
def monkey
|
106
|
+
raise CarrierWave::ProcessingError, "Ohh noez!"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
@instance.image = stub_file('test.jpg')
|
110
|
+
end
|
111
|
+
|
69
112
|
end
|
70
113
|
|
71
114
|
describe '#image_cache' do
|
@@ -140,6 +183,51 @@ describe CarrierWave::Mount do
|
|
140
183
|
@instance.image.current_path.should == public_path('uploads/test.jpg')
|
141
184
|
end
|
142
185
|
end
|
186
|
+
|
187
|
+
describe '#image_integrity_error' do
|
188
|
+
|
189
|
+
it "should be nil by default" do
|
190
|
+
@instance.image_integrity_error.should be_nil
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should be nil after a file is cached" do
|
194
|
+
@instance.image = stub_file('test.jpg')
|
195
|
+
@instance.image_integrity_error.should be_nil
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should be an error instance after an integrity check has failed" do
|
199
|
+
@uploader.class_eval do
|
200
|
+
def extension_white_list
|
201
|
+
%(txt)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
@instance.image = stub_file('test.jpg')
|
205
|
+
@instance.image_integrity_error.should be_an_instance_of(CarrierWave::IntegrityError)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe '#image_processing_error' do
|
210
|
+
|
211
|
+
it "should be nil by default" do
|
212
|
+
@instance.image_processing_error.should be_nil
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should be nil after a file is cached" do
|
216
|
+
@instance.image = stub_file('test.jpg')
|
217
|
+
@instance.image_processing_error.should be_nil
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should be an error instance after an integrity check has failed" do
|
221
|
+
@uploader.class_eval do
|
222
|
+
process :monkey
|
223
|
+
def monkey
|
224
|
+
raise CarrierWave::ProcessingError, "Ohh noez!"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
@instance.image = stub_file('test.jpg')
|
228
|
+
@instance.image_processing_error.should be_an_instance_of(CarrierWave::ProcessingError)
|
229
|
+
end
|
230
|
+
end
|
143
231
|
|
144
232
|
end
|
145
233
|
|
@@ -178,4 +266,60 @@ describe CarrierWave::Mount do
|
|
178
266
|
|
179
267
|
end
|
180
268
|
|
269
|
+
describe '#mount_uploader with :ignore_integrity_errors => false' do
|
270
|
+
|
271
|
+
before do
|
272
|
+
@class = Class.new
|
273
|
+
@class.send(:extend, CarrierWave::Mount)
|
274
|
+
|
275
|
+
@uploader = Class.new do
|
276
|
+
include CarrierWave::Uploader
|
277
|
+
end
|
278
|
+
|
279
|
+
@class.mount_uploader(:image, @uploader, :ignore_integrity_errors => false)
|
280
|
+
@instance = @class.new
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should raise an error if the image fails an integrity check" do
|
284
|
+
@uploader.class_eval do
|
285
|
+
def extension_white_list
|
286
|
+
%(txt)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
running {
|
290
|
+
@instance.image = stub_file('test.jpg')
|
291
|
+
}.should raise_error(CarrierWave::IntegrityError)
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
describe '#mount_uploader with :ignore_processing_errors => false' do
|
297
|
+
|
298
|
+
before do
|
299
|
+
@class = Class.new
|
300
|
+
@class.send(:extend, CarrierWave::Mount)
|
301
|
+
|
302
|
+
@uploader = Class.new do
|
303
|
+
include CarrierWave::Uploader
|
304
|
+
end
|
305
|
+
|
306
|
+
@class.mount_uploader(:image, @uploader, :ignore_processing_errors => false)
|
307
|
+
@instance = @class.new
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should raise an error if the image fails to be processed" do
|
311
|
+
@uploader.class_eval do
|
312
|
+
process :monkey
|
313
|
+
def monkey
|
314
|
+
raise CarrierWave::ProcessingError, "Ohh noez!"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
running {
|
318
|
+
@instance.image = stub_file('test.jpg')
|
319
|
+
}.should raise_error(CarrierWave::ProcessingError)
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
|
181
325
|
end
|
@@ -28,8 +28,6 @@ class Event < ActiveRecord::Base; end # setup a basic AR class for testing
|
|
28
28
|
|
29
29
|
describe CarrierWave::ActiveRecord do
|
30
30
|
|
31
|
-
include SanitizedFileSpecHelper
|
32
|
-
|
33
31
|
describe '.mount_uploader' do
|
34
32
|
|
35
33
|
before(:all) { TestMigration.up }
|
@@ -39,7 +37,9 @@ describe CarrierWave::ActiveRecord do
|
|
39
37
|
before do
|
40
38
|
@class = Class.new(ActiveRecord::Base)
|
41
39
|
@class.table_name = "events"
|
42
|
-
@uploader = Class.new
|
40
|
+
@uploader = Class.new do
|
41
|
+
include CarrierWave::Uploader
|
42
|
+
end
|
43
43
|
@class.mount_uploader(:image, @uploader)
|
44
44
|
@event = @class.new
|
45
45
|
end
|
@@ -98,6 +98,27 @@ describe CarrierWave::ActiveRecord do
|
|
98
98
|
@event.image = ''
|
99
99
|
@event.image.should be_nil
|
100
100
|
end
|
101
|
+
|
102
|
+
it "should make the record invalid when an integrity error occurs" do
|
103
|
+
@uploader.class_eval do
|
104
|
+
def extension_white_list
|
105
|
+
%(txt)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
@event.image = stub_file('test.jpg')
|
109
|
+
@event.should_not be_valid
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should make the record invalid when a processing error occurs" do
|
113
|
+
@uploader.class_eval do
|
114
|
+
process :monkey
|
115
|
+
def monkey
|
116
|
+
raise CarrierWave::ProcessingError, "Ohh noez!"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
@event.image = stub_file('test.jpg')
|
120
|
+
@event.should_not be_valid
|
121
|
+
end
|
101
122
|
|
102
123
|
end
|
103
124
|
|
data/spec/orm/datamapper_spec.rb
CHANGED
@@ -6,10 +6,10 @@ DataMapper.setup(:default, 'sqlite3::memory:')
|
|
6
6
|
|
7
7
|
describe CarrierWave::DataMapper do
|
8
8
|
|
9
|
-
include SanitizedFileSpecHelper
|
10
|
-
|
11
9
|
before do
|
12
|
-
uploader = Class.new
|
10
|
+
uploader = Class.new do
|
11
|
+
include CarrierWave::Uploader
|
12
|
+
end
|
13
13
|
|
14
14
|
@class = Class.new
|
15
15
|
@class.class_eval do
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
require 'carrierwave/orm/sequel'
|
4
|
+
|
5
|
+
DB = Sequel.sqlite
|
6
|
+
|
7
|
+
describe CarrierWave::Sequel do
|
8
|
+
|
9
|
+
def setup_variables_for_class(klass)
|
10
|
+
uploader = Class.new do
|
11
|
+
include CarrierWave::Uploader
|
12
|
+
end
|
13
|
+
klass.mount_uploader(:image, uploader)
|
14
|
+
model = klass.new
|
15
|
+
[klass, uploader, model]
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.mount_uploader' do
|
19
|
+
|
20
|
+
before(:all) do
|
21
|
+
DB.create_table :events do
|
22
|
+
primary_key :id
|
23
|
+
column :image, :string
|
24
|
+
column :textfile, :string
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
after(:all) do
|
29
|
+
DB.drop_table :events
|
30
|
+
end
|
31
|
+
|
32
|
+
before do
|
33
|
+
@class = Class.new(Sequel::Model)
|
34
|
+
@class.set_dataset :events
|
35
|
+
@class, @uploader, @event = setup_variables_for_class(@class)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#image' do
|
39
|
+
|
40
|
+
it "should return nil when nothing has been assigned" do
|
41
|
+
@event.image.should be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return nil when an empty string has been assigned" do
|
45
|
+
@event[:image] = ''
|
46
|
+
@event.save
|
47
|
+
@event.reload
|
48
|
+
@event.image.should be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should retrieve a file from the storage if a value is stored in the database" do
|
52
|
+
@event[:image] = 'test.jpeg'
|
53
|
+
@event.save
|
54
|
+
@event.reload
|
55
|
+
@event.image.should be_an_instance_of(@uploader)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should set the path to the store dir" do
|
59
|
+
@event[:image] = 'test.jpeg'
|
60
|
+
@event.save
|
61
|
+
@event.reload
|
62
|
+
@event.image.current_path.should == public_path('uploads/test.jpeg')
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#image=' do
|
68
|
+
|
69
|
+
it "should cache a file" do
|
70
|
+
@event.image = stub_file('test.jpeg')
|
71
|
+
@event.image.should be_an_instance_of(@uploader)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should write nothing to the database, to prevent overriden filenames to fail because of unassigned attributes" do
|
75
|
+
@event[:image].should be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should copy a file into into the cache directory" do
|
79
|
+
@event.image = stub_file('test.jpeg')
|
80
|
+
@event.image.current_path.should =~ /^#{public_path('uploads/tmp')}/
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should do nothing when nil is assigned" do
|
84
|
+
@event.image = nil
|
85
|
+
@event.image.should be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should do nothing when an empty string is assigned" do
|
89
|
+
@event.image = ''
|
90
|
+
@event.image.should be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#save' do
|
96
|
+
|
97
|
+
it "should do nothing when no file has been assigned" do
|
98
|
+
@event.save.should be_true
|
99
|
+
@event.image.should be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should copy the file to the upload directory when a file has been assigned" do
|
103
|
+
@event.image = stub_file('test.jpeg')
|
104
|
+
@event.save.should be_true
|
105
|
+
@event.image.should be_an_instance_of(@uploader)
|
106
|
+
@event.image.current_path.should == public_path('uploads/test.jpeg')
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'with validation' do
|
110
|
+
|
111
|
+
before do
|
112
|
+
@class.class_eval do
|
113
|
+
validates_each :image do |object, attribute, value|
|
114
|
+
object.errors[attribute] << 'FAIL!'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should do nothing when a validation fails" do
|
120
|
+
pending "I don't understand how this is supposed to work :S" do
|
121
|
+
@event.image = stub_file('test.jpeg')
|
122
|
+
@event.save.should be_false
|
123
|
+
@event.image.should be_an_instance_of(@uploader)
|
124
|
+
@event.image.current_path.should =~ /^#{public_path('uploads/tmp')}/
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should assign the filename to the database" do
|
130
|
+
@event.image = stub_file('test.jpeg')
|
131
|
+
@event.save.should be_true
|
132
|
+
@event.reload
|
133
|
+
@event[:image].should == 'test.jpeg'
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'with overriddent filename' do
|
139
|
+
|
140
|
+
describe '#save' do
|
141
|
+
|
142
|
+
before do
|
143
|
+
@uploader.class_eval do
|
144
|
+
def filename
|
145
|
+
model.name + File.extname(super)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
@event.stub!(:name).and_return('jonas')
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should copy the file to the upload directory when a file has been assigned" do
|
152
|
+
@event.image = stub_file('test.jpeg')
|
153
|
+
@event.save.should be_true
|
154
|
+
@event.image.should be_an_instance_of(@uploader)
|
155
|
+
@event.image.current_path.should == public_path('uploads/jonas.jpeg')
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should assign an overridden filename to the database" do
|
159
|
+
@event.image = stub_file('test.jpeg')
|
160
|
+
@event.save.should be_true
|
161
|
+
@event.reload
|
162
|
+
@event[:image].should == 'jonas.jpeg'
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|