alg-paperclip 2.3.1.1

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 (50) hide show
  1. data/LICENSE +26 -0
  2. data/README.rdoc +195 -0
  3. data/Rakefile +103 -0
  4. data/generators/paperclip/USAGE +5 -0
  5. data/generators/paperclip/paperclip_generator.rb +27 -0
  6. data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  7. data/init.rb +1 -0
  8. data/lib/paperclip.rb +357 -0
  9. data/lib/paperclip/attachment.rb +345 -0
  10. data/lib/paperclip/callback_compatability.rb +33 -0
  11. data/lib/paperclip/geometry.rb +115 -0
  12. data/lib/paperclip/interpolations.rb +120 -0
  13. data/lib/paperclip/iostream.rb +59 -0
  14. data/lib/paperclip/matchers.rb +4 -0
  15. data/lib/paperclip/matchers/have_attached_file_matcher.rb +49 -0
  16. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +65 -0
  17. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +48 -0
  18. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +85 -0
  19. data/lib/paperclip/processor.rb +49 -0
  20. data/lib/paperclip/storage.rb +247 -0
  21. data/lib/paperclip/style.rb +90 -0
  22. data/lib/paperclip/thumbnail.rb +75 -0
  23. data/lib/paperclip/upfile.rb +49 -0
  24. data/shoulda_macros/paperclip.rb +117 -0
  25. data/tasks/paperclip_tasks.rake +79 -0
  26. data/test/attachment_test.rb +788 -0
  27. data/test/database.yml +4 -0
  28. data/test/fixtures/12k.png +0 -0
  29. data/test/fixtures/50x50.png +0 -0
  30. data/test/fixtures/5k.png +0 -0
  31. data/test/fixtures/bad.png +1 -0
  32. data/test/fixtures/s3.yml +8 -0
  33. data/test/fixtures/text.txt +0 -0
  34. data/test/fixtures/twopage.pdf +0 -0
  35. data/test/geometry_test.rb +177 -0
  36. data/test/helper.rb +108 -0
  37. data/test/integration_test.rb +483 -0
  38. data/test/interpolations_test.rb +124 -0
  39. data/test/iostream_test.rb +78 -0
  40. data/test/matchers/have_attached_file_matcher_test.rb +21 -0
  41. data/test/matchers/validate_attachment_content_type_matcher_test.rb +31 -0
  42. data/test/matchers/validate_attachment_presence_matcher_test.rb +23 -0
  43. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  44. data/test/paperclip_test.rb +298 -0
  45. data/test/processor_test.rb +10 -0
  46. data/test/storage_test.rb +330 -0
  47. data/test/style_test.rb +141 -0
  48. data/test/thumbnail_test.rb +227 -0
  49. data/test/upfile_test.rb +28 -0
  50. metadata +164 -0
@@ -0,0 +1,10 @@
1
+ require 'test/helper'
2
+
3
+ class ProcessorTest < Test::Unit::TestCase
4
+ should "instantiate and call #make when sent #make to the class" do
5
+ processor = mock
6
+ processor.expects(:make).with()
7
+ Paperclip::Processor.expects(:new).with(:one, :two, :three).returns(processor)
8
+ Paperclip::Processor.make(:one, :two, :three)
9
+ end
10
+ end
@@ -0,0 +1,330 @@
1
+ require 'test/helper'
2
+ require 'aws/s3'
3
+
4
+ class StorageTest < Test::Unit::TestCase
5
+ def rails_env(env)
6
+ silence_warnings do
7
+ Object.const_set(:RAILS_ENV, env)
8
+ end
9
+ end
10
+
11
+ context "Parsing S3 credentials" do
12
+ setup do
13
+ AWS::S3::Base.stubs(:establish_connection!)
14
+ rebuild_model :storage => :s3,
15
+ :bucket => "testing",
16
+ :s3_credentials => {:not => :important}
17
+
18
+ @dummy = Dummy.new
19
+ @avatar = @dummy.avatar
20
+
21
+ @current_env = RAILS_ENV
22
+ end
23
+
24
+ teardown do
25
+ rails_env(@current_env)
26
+ end
27
+
28
+ should "get the correct credentials when RAILS_ENV is production" do
29
+ rails_env("production")
30
+ assert_equal({:key => "12345"},
31
+ @avatar.parse_credentials('production' => {:key => '12345'},
32
+ :development => {:key => "54321"}))
33
+ end
34
+
35
+ should "get the correct credentials when RAILS_ENV is development" do
36
+ rails_env("development")
37
+ assert_equal({:key => "54321"},
38
+ @avatar.parse_credentials('production' => {:key => '12345'},
39
+ :development => {:key => "54321"}))
40
+ end
41
+
42
+ should "return the argument if the key does not exist" do
43
+ rails_env("not really an env")
44
+ assert_equal({:test => "12345"}, @avatar.parse_credentials(:test => "12345"))
45
+ end
46
+ end
47
+
48
+ context "" do
49
+ setup do
50
+ AWS::S3::Base.stubs(:establish_connection!)
51
+ rebuild_model :storage => :s3,
52
+ :s3_credentials => {},
53
+ :bucket => "bucket",
54
+ :path => ":attachment/:basename.:extension",
55
+ :url => ":s3_path_url"
56
+ @dummy = Dummy.new
57
+ @dummy.avatar = StringIO.new(".")
58
+ end
59
+
60
+ should "return a url based on an S3 path" do
61
+ assert_match %r{^http://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
62
+ end
63
+ end
64
+ context "" do
65
+ setup do
66
+ AWS::S3::Base.stubs(:establish_connection!)
67
+ rebuild_model :storage => :s3,
68
+ :s3_credentials => {},
69
+ :bucket => "bucket",
70
+ :path => ":attachment/:basename.:extension",
71
+ :url => ":s3_domain_url"
72
+ @dummy = Dummy.new
73
+ @dummy.avatar = StringIO.new(".")
74
+ end
75
+
76
+ should "return a url based on an S3 subdomain" do
77
+ assert_match %r{^http://bucket.s3.amazonaws.com/avatars/stringio.txt}, @dummy.avatar.url
78
+ end
79
+ end
80
+ context "" do
81
+ setup do
82
+ AWS::S3::Base.stubs(:establish_connection!)
83
+ rebuild_model :storage => :s3,
84
+ :s3_credentials => {
85
+ :production => { :bucket => "prod_bucket" },
86
+ :development => { :bucket => "dev_bucket" }
87
+ },
88
+ :s3_host_alias => "something.something.com",
89
+ :path => ":attachment/:basename.:extension",
90
+ :url => ":s3_alias_url"
91
+ @dummy = Dummy.new
92
+ @dummy.avatar = StringIO.new(".")
93
+ end
94
+
95
+ should "return a url based on the host_alias" do
96
+ assert_match %r{^http://something.something.com/avatars/stringio.txt}, @dummy.avatar.url
97
+ end
98
+ end
99
+
100
+ context "Generating a url with an expiration" do
101
+ setup do
102
+ AWS::S3::Base.stubs(:establish_connection!)
103
+ rebuild_model :storage => :s3,
104
+ :s3_credentials => {
105
+ :production => { :bucket => "prod_bucket" },
106
+ :development => { :bucket => "dev_bucket" }
107
+ },
108
+ :s3_host_alias => "something.something.com",
109
+ :path => ":attachment/:basename.:extension",
110
+ :url => ":s3_alias_url"
111
+
112
+ rails_env("production")
113
+
114
+ @dummy = Dummy.new
115
+ @dummy.avatar = StringIO.new(".")
116
+
117
+ AWS::S3::S3Object.expects(:url_for).with("avatars/stringio.txt", "prod_bucket", { :expires_in => 3600 })
118
+
119
+ @dummy.avatar.expiring_url
120
+ end
121
+
122
+ should "should succeed" do
123
+ assert true
124
+ end
125
+ end
126
+
127
+ context "Parsing S3 credentials with a bucket in them" do
128
+ setup do
129
+ AWS::S3::Base.stubs(:establish_connection!)
130
+ rebuild_model :storage => :s3,
131
+ :s3_credentials => {
132
+ :production => { :bucket => "prod_bucket" },
133
+ :development => { :bucket => "dev_bucket" }
134
+ }
135
+ @dummy = Dummy.new
136
+ @old_env = RAILS_ENV
137
+ end
138
+
139
+ teardown{ rails_env(@old_env) }
140
+
141
+ should "get the right bucket in production" do
142
+ rails_env("production")
143
+ assert_equal "prod_bucket", @dummy.avatar.bucket_name
144
+ end
145
+
146
+ should "get the right bucket in development" do
147
+ rails_env("development")
148
+ assert_equal "dev_bucket", @dummy.avatar.bucket_name
149
+ end
150
+ end
151
+
152
+ context "An attachment with S3 storage" do
153
+ setup do
154
+ rebuild_model :storage => :s3,
155
+ :bucket => "testing",
156
+ :path => ":attachment/:style/:basename.:extension",
157
+ :s3_credentials => {
158
+ 'access_key_id' => "12345",
159
+ 'secret_access_key' => "54321"
160
+ }
161
+ end
162
+
163
+ should "be extended by the S3 module" do
164
+ assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
165
+ end
166
+
167
+ should "not be extended by the Filesystem module" do
168
+ assert ! Dummy.new.avatar.is_a?(Paperclip::Storage::Filesystem)
169
+ end
170
+
171
+ context "when assigned" do
172
+ setup do
173
+ @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
174
+ @dummy = Dummy.new
175
+ @dummy.avatar = @file
176
+ end
177
+
178
+ teardown { @file.close }
179
+
180
+ should "not get a bucket to get a URL" do
181
+ @dummy.avatar.expects(:s3).never
182
+ @dummy.avatar.expects(:s3_bucket).never
183
+ assert_match %r{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
184
+ end
185
+
186
+ context "and saved" do
187
+ setup do
188
+ AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path, anything, 'testing', :content_type => 'image/png', :access => :public_read)
189
+ @dummy.save
190
+ end
191
+
192
+ should "succeed" do
193
+ assert true
194
+ end
195
+ end
196
+
197
+ context "and remove" do
198
+ setup do
199
+ AWS::S3::S3Object.stubs(:exists?).returns(true)
200
+ AWS::S3::S3Object.stubs(:delete)
201
+ @dummy.destroy_attached_files
202
+ end
203
+
204
+ should "succeed" do
205
+ assert true
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ context "An attachment with S3 storage and bucket defined as a Proc" do
212
+ setup do
213
+ AWS::S3::Base.stubs(:establish_connection!)
214
+ rebuild_model :storage => :s3,
215
+ :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
216
+ :s3_credentials => {:not => :important}
217
+ end
218
+
219
+ should "get the right bucket name" do
220
+ assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
221
+ assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
222
+ end
223
+ end
224
+
225
+ context "An attachment with S3 storage and specific s3 headers set" do
226
+ setup do
227
+ AWS::S3::Base.stubs(:establish_connection!)
228
+ rebuild_model :storage => :s3,
229
+ :bucket => "testing",
230
+ :path => ":attachment/:style/:basename.:extension",
231
+ :s3_credentials => {
232
+ 'access_key_id' => "12345",
233
+ 'secret_access_key' => "54321"
234
+ },
235
+ :s3_headers => {'Cache-Control' => 'max-age=31557600'}
236
+ end
237
+
238
+ context "when assigned" do
239
+ setup do
240
+ @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
241
+ @dummy = Dummy.new
242
+ @dummy.avatar = @file
243
+ end
244
+
245
+ teardown { @file.close }
246
+
247
+ context "and saved" do
248
+ setup do
249
+ AWS::S3::Base.stubs(:establish_connection!)
250
+ AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path,
251
+ anything,
252
+ 'testing',
253
+ :content_type => 'image/png',
254
+ :access => :public_read,
255
+ 'Cache-Control' => 'max-age=31557600')
256
+ @dummy.save
257
+ end
258
+
259
+ should "succeed" do
260
+ assert true
261
+ end
262
+ end
263
+ end
264
+ end
265
+
266
+ context "with S3 credentials in a YAML file" do
267
+ setup do
268
+ ENV['S3_KEY'] = 'env_key'
269
+ ENV['S3_BUCKET'] = 'env_bucket'
270
+ ENV['S3_SECRET'] = 'env_secret'
271
+
272
+ rails_env('test')
273
+
274
+ rebuild_model :storage => :s3,
275
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "fixtures/s3.yml"))
276
+
277
+ Dummy.delete_all
278
+
279
+ @dummy = Dummy.new
280
+ end
281
+
282
+ should "run it the file through ERB" do
283
+ assert_equal 'env_bucket', @dummy.avatar.bucket_name
284
+ assert_equal 'env_key', AWS::S3::Base.connection.options[:access_key_id]
285
+ assert_equal 'env_secret', AWS::S3::Base.connection.options[:secret_access_key]
286
+ end
287
+ end
288
+
289
+ unless ENV["S3_TEST_BUCKET"].blank?
290
+ context "Using S3 for real, an attachment with S3 storage" do
291
+ setup do
292
+ rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
293
+ :storage => :s3,
294
+ :bucket => ENV["S3_TEST_BUCKET"],
295
+ :path => ":class/:attachment/:id/:style.:extension",
296
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml"))
297
+
298
+ Dummy.delete_all
299
+ @dummy = Dummy.new
300
+ end
301
+
302
+ should "be extended by the S3 module" do
303
+ assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
304
+ end
305
+
306
+ context "when assigned" do
307
+ setup do
308
+ @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
309
+ @dummy.avatar = @file
310
+ end
311
+
312
+ teardown { @file.close }
313
+
314
+ should "still return a Tempfile when sent #to_file" do
315
+ assert_equal Tempfile, @dummy.avatar.to_file.class
316
+ end
317
+
318
+ context "and saved" do
319
+ setup do
320
+ @dummy.save
321
+ end
322
+
323
+ should "be on S3" do
324
+ assert true
325
+ end
326
+ end
327
+ end
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+ require 'test/helper'
3
+
4
+ class StyleTest < Test::Unit::TestCase
5
+
6
+ context "A style rule" do
7
+ setup do
8
+ @attachment = attachment :path => ":basename.:extension",
9
+ :styles => { :foo => {:geometry => "100x100#", :format => :png} }
10
+ @style = @attachment.styles[:foo]
11
+ end
12
+
13
+ should "be held as a Style object" do
14
+ assert_kind_of Paperclip::Style, @style
15
+ end
16
+
17
+ should "get processors from the attachment definition" do
18
+ assert_equal [:thumbnail], @style.processors
19
+ end
20
+
21
+ should "have the right geometry" do
22
+ assert_equal "100x100#", @style.geometry
23
+ end
24
+
25
+ should "be whiny if the attachment is" do
26
+ @attachment.expects(:whiny).returns(true)
27
+ assert @style.whiny?
28
+ end
29
+
30
+ should "respond to hash notation" do
31
+ assert_equal [:thumbnail], @style[:processors]
32
+ assert_equal "100x100#", @style[:geometry]
33
+ end
34
+ end
35
+
36
+ context "A style rule with properties supplied as procs" do
37
+ setup do
38
+ @attachment = attachment :path => ":basename.:extension",
39
+ :whiny_thumbnails => true,
40
+ :processors => lambda {|a| [:test]},
41
+ :styles => {
42
+ :foo => lambda{|a| "300x300#"},
43
+ :bar => {
44
+ :geometry => lambda{|a| "300x300#"}
45
+ }
46
+ }
47
+ end
48
+
49
+ should "defer processing of procs until they are needed" do
50
+ assert_kind_of Proc, @attachment.styles[:foo].instance_variable_get("@geometry")
51
+ assert_kind_of Proc, @attachment.styles[:bar].instance_variable_get("@geometry")
52
+ assert_kind_of Proc, @attachment.instance_variable_get("@processors")
53
+ end
54
+
55
+ should "call procs when they are needed" do
56
+ assert_equal "300x300#", @attachment.styles[:foo].geometry
57
+ assert_equal "300x300#", @attachment.styles[:bar].geometry
58
+ assert_equal [:test], @attachment.styles[:foo].processors
59
+ assert_equal [:test], @attachment.styles[:bar].processors
60
+ end
61
+ end
62
+
63
+ context "An attachment with style rules in various forms" do
64
+ setup do
65
+ @attachment = attachment :path => ":basename.:extension",
66
+ :styles => {
67
+ :aslist => ["100x100", :png],
68
+ :ashash => {:geometry => "100x100", :format => :png},
69
+ :asstring => "100x100"
70
+ }
71
+ end
72
+ should "have the right number of styles" do
73
+ assert_kind_of Hash, @attachment.styles
74
+ assert_equal 3, @attachment.styles.size
75
+ end
76
+
77
+ should "have styles as Style objects" do
78
+ [:aslist, :ashash, :aslist].each do |s|
79
+ assert_kind_of Paperclip::Style, @attachment.styles[s]
80
+ end
81
+ end
82
+
83
+ should "have the right geometries" do
84
+ [:aslist, :ashash, :aslist].each do |s|
85
+ assert_equal @attachment.styles[s].geometry, "100x100"
86
+ end
87
+ end
88
+
89
+ should "have the right formats" do
90
+ assert_equal @attachment.styles[:aslist].format, :png
91
+ assert_equal @attachment.styles[:ashash].format, :png
92
+ assert_nil @attachment.styles[:asstring].format
93
+ end
94
+
95
+ end
96
+
97
+ context "An attachment with :convert_options" do
98
+ setup do
99
+ @attachment = attachment :path => ":basename.:extension",
100
+ :styles => {:thumb => "100x100", :large => "400x400"},
101
+ :convert_options => {:all => "-do_stuff", :thumb => "-thumbnailize"}
102
+ @style = @attachment.styles[:thumb]
103
+ @file = StringIO.new("...")
104
+ @file.stubs(:original_filename).returns("file.jpg")
105
+ end
106
+
107
+ before_should "not have called extra_options_for(:thumb/:large) on initialization" do
108
+ @attachment.expects(:extra_options_for).never
109
+ end
110
+
111
+ should "call extra_options_for(:thumb/:large) when convert options are requested" do
112
+ @attachment.expects(:extra_options_for).with(:thumb)
113
+ @attachment.styles[:thumb].convert_options
114
+ end
115
+ end
116
+
117
+ context "A style rule with its own :processors" do
118
+ setup do
119
+ @attachment = attachment :path => ":basename.:extension",
120
+ :styles => {
121
+ :foo => {
122
+ :geometry => "100x100#",
123
+ :format => :png,
124
+ :processors => [:test]
125
+ }
126
+ },
127
+ :processors => [:thumbnail]
128
+ @style = @attachment.styles[:foo]
129
+ end
130
+
131
+ should "not get processors from the attachment" do
132
+ @attachment.expects(:processors).never
133
+ assert_not_equal [:thumbnail], @style.processors
134
+ end
135
+
136
+ should "report its own processors" do
137
+ assert_equal [:test], @style.processors
138
+ end
139
+
140
+ end
141
+ end