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