cemeng-paperclip 2.3.6

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 (62) hide show
  1. data/LICENSE +26 -0
  2. data/README.rdoc +182 -0
  3. data/Rakefile +80 -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 +402 -0
  12. data/lib/paperclip/attachment.rb +347 -0
  13. data/lib/paperclip/callback_compatability.rb +61 -0
  14. data/lib/paperclip/command_line.rb +80 -0
  15. data/lib/paperclip/geometry.rb +115 -0
  16. data/lib/paperclip/interpolations.rb +114 -0
  17. data/lib/paperclip/iostream.rb +45 -0
  18. data/lib/paperclip/matchers.rb +33 -0
  19. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  20. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +75 -0
  21. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  22. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  23. data/lib/paperclip/processor.rb +58 -0
  24. data/lib/paperclip/railtie.rb +25 -0
  25. data/lib/paperclip/storage.rb +3 -0
  26. data/lib/paperclip/storage/database.rb +204 -0
  27. data/lib/paperclip/storage/filesystem.rb +73 -0
  28. data/lib/paperclip/storage/s3.rb +192 -0
  29. data/lib/paperclip/style.rb +91 -0
  30. data/lib/paperclip/thumbnail.rb +79 -0
  31. data/lib/paperclip/upfile.rb +55 -0
  32. data/lib/paperclip/version.rb +3 -0
  33. data/lib/tasks/paperclip.rake +79 -0
  34. data/rails/init.rb +2 -0
  35. data/shoulda_macros/paperclip.rb +118 -0
  36. data/test/attachment_test.rb +804 -0
  37. data/test/command_line_test.rb +133 -0
  38. data/test/database.yml +4 -0
  39. data/test/database_storage_test.rb +267 -0
  40. data/test/fixtures/12k.png +0 -0
  41. data/test/fixtures/50x50.png +0 -0
  42. data/test/fixtures/5k.png +0 -0
  43. data/test/fixtures/bad.png +1 -0
  44. data/test/fixtures/s3.yml +8 -0
  45. data/test/fixtures/text.txt +0 -0
  46. data/test/fixtures/twopage.pdf +0 -0
  47. data/test/geometry_test.rb +177 -0
  48. data/test/helper.rb +146 -0
  49. data/test/integration_test.rb +482 -0
  50. data/test/interpolations_test.rb +127 -0
  51. data/test/iostream_test.rb +71 -0
  52. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  53. data/test/matchers/validate_attachment_content_type_matcher_test.rb +47 -0
  54. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  55. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  56. data/test/paperclip_test.rb +254 -0
  57. data/test/processor_test.rb +10 -0
  58. data/test/storage_test.rb +363 -0
  59. data/test/style_test.rb +141 -0
  60. data/test/thumbnail_test.rb +227 -0
  61. data/test/upfile_test.rb +36 -0
  62. metadata +186 -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,363 @@
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 saved without a bucket" do
189
+ setup do
190
+ class AWS::S3::NoSuchBucket < AWS::S3::ResponseError
191
+ # Force the class to be created as a proper subclass of ResponseError thanks to AWS::S3's autocreation of exceptions
192
+ end
193
+ AWS::S3::Bucket.expects(:create).with("testing")
194
+ AWS::S3::S3Object.stubs(:store).raises(AWS::S3::NoSuchBucket.new(:message, :response)).then.returns(true)
195
+ @dummy.save
196
+ end
197
+
198
+ should "succeed" do
199
+ assert true
200
+ end
201
+ end
202
+
203
+ context "and remove" do
204
+ setup do
205
+ AWS::S3::S3Object.stubs(:exists?).returns(true)
206
+ AWS::S3::S3Object.stubs(:delete)
207
+ @dummy.destroy_attached_files
208
+ end
209
+
210
+ should "succeed" do
211
+ assert true
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ context "An attachment with S3 storage and bucket defined as a Proc" do
218
+ setup do
219
+ AWS::S3::Base.stubs(:establish_connection!)
220
+ rebuild_model :storage => :s3,
221
+ :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
222
+ :s3_credentials => {:not => :important}
223
+ end
224
+
225
+ should "get the right bucket name" do
226
+ assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
227
+ assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
228
+ end
229
+ end
230
+
231
+ context "An attachment with S3 storage and specific s3 headers set" do
232
+ setup do
233
+ AWS::S3::Base.stubs(:establish_connection!)
234
+ rebuild_model :storage => :s3,
235
+ :bucket => "testing",
236
+ :path => ":attachment/:style/:basename.:extension",
237
+ :s3_credentials => {
238
+ 'access_key_id' => "12345",
239
+ 'secret_access_key' => "54321"
240
+ },
241
+ :s3_headers => {'Cache-Control' => 'max-age=31557600'}
242
+ end
243
+
244
+ context "when assigned" do
245
+ setup do
246
+ @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
247
+ @dummy = Dummy.new
248
+ @dummy.avatar = @file
249
+ end
250
+
251
+ teardown { @file.close }
252
+
253
+ context "and saved" do
254
+ setup do
255
+ AWS::S3::Base.stubs(:establish_connection!)
256
+ AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path,
257
+ anything,
258
+ 'testing',
259
+ :content_type => 'image/png',
260
+ :access => :public_read,
261
+ 'Cache-Control' => 'max-age=31557600')
262
+ @dummy.save
263
+ end
264
+
265
+ should "succeed" do
266
+ assert true
267
+ end
268
+ end
269
+ end
270
+ end
271
+
272
+ context "with S3 credentials supplied as Pathname" do
273
+ setup do
274
+ ENV['S3_KEY'] = 'pathname_key'
275
+ ENV['S3_BUCKET'] = 'pathname_bucket'
276
+ ENV['S3_SECRET'] = 'pathname_secret'
277
+
278
+ rails_env('test')
279
+
280
+ rebuild_model :storage => :s3,
281
+ :s3_credentials => Pathname.new(File.join(File.dirname(__FILE__))).join("fixtures/s3.yml")
282
+
283
+ Dummy.delete_all
284
+ @dummy = Dummy.new
285
+ end
286
+
287
+ should "parse the credentials" do
288
+ assert_equal 'pathname_bucket', @dummy.avatar.bucket_name
289
+ assert_equal 'pathname_key', AWS::S3::Base.connection.options[:access_key_id]
290
+ assert_equal 'pathname_secret', AWS::S3::Base.connection.options[:secret_access_key]
291
+ end
292
+ end
293
+
294
+ context "with S3 credentials in a YAML file" do
295
+ setup do
296
+ ENV['S3_KEY'] = 'env_key'
297
+ ENV['S3_BUCKET'] = 'env_bucket'
298
+ ENV['S3_SECRET'] = 'env_secret'
299
+
300
+ rails_env('test')
301
+
302
+ rebuild_model :storage => :s3,
303
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "fixtures/s3.yml"))
304
+
305
+ Dummy.delete_all
306
+
307
+ @dummy = Dummy.new
308
+ end
309
+
310
+ should "run it the file through ERB" do
311
+ assert_equal 'env_bucket', @dummy.avatar.bucket_name
312
+ assert_equal 'env_key', AWS::S3::Base.connection.options[:access_key_id]
313
+ assert_equal 'env_secret', AWS::S3::Base.connection.options[:secret_access_key]
314
+ end
315
+ end
316
+
317
+ unless ENV["S3_TEST_BUCKET"].blank?
318
+ context "Using S3 for real, an attachment with S3 storage" do
319
+ setup do
320
+ rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
321
+ :storage => :s3,
322
+ :bucket => ENV["S3_TEST_BUCKET"],
323
+ :path => ":class/:attachment/:id/:style.:extension",
324
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml"))
325
+
326
+ Dummy.delete_all
327
+ @dummy = Dummy.new
328
+ end
329
+
330
+ should "be extended by the S3 module" do
331
+ assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
332
+ end
333
+
334
+ context "when assigned" do
335
+ setup do
336
+ @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
337
+ @dummy.avatar = @file
338
+ end
339
+
340
+ teardown { @file.close }
341
+
342
+ should "still return a Tempfile when sent #to_file" do
343
+ assert_equal Paperclip::Tempfile, @dummy.avatar.to_file.class
344
+ end
345
+
346
+ context "and saved" do
347
+ setup do
348
+ @dummy.save
349
+ end
350
+
351
+ should "be on S3" do
352
+ assert true
353
+ end
354
+
355
+ should "generate a tempfile with the right name" do
356
+ file = @dummy.avatar.to_file
357
+ assert_match /^original.*\.png$/, File.basename(file.path)
358
+ end
359
+ end
360
+ end
361
+ end
362
+ end
363
+ 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