mender_paperclip 2.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/LICENSE +26 -0
  2. data/README.md +402 -0
  3. data/Rakefile +86 -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 +4 -0
  8. data/lib/generators/paperclip/USAGE +8 -0
  9. data/lib/generators/paperclip/paperclip_generator.rb +33 -0
  10. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  11. data/lib/paperclip/attachment.rb +454 -0
  12. data/lib/paperclip/callback_compatibility.rb +61 -0
  13. data/lib/paperclip/geometry.rb +120 -0
  14. data/lib/paperclip/interpolations.rb +181 -0
  15. data/lib/paperclip/iostream.rb +45 -0
  16. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  17. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +81 -0
  18. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  19. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  20. data/lib/paperclip/matchers.rb +33 -0
  21. data/lib/paperclip/missing_attachment_styles.rb +87 -0
  22. data/lib/paperclip/options.rb +79 -0
  23. data/lib/paperclip/processor.rb +58 -0
  24. data/lib/paperclip/railtie.rb +26 -0
  25. data/lib/paperclip/storage/filesystem.rb +81 -0
  26. data/lib/paperclip/storage/fog.rb +162 -0
  27. data/lib/paperclip/storage/s3.rb +262 -0
  28. data/lib/paperclip/storage.rb +3 -0
  29. data/lib/paperclip/style.rb +95 -0
  30. data/lib/paperclip/thumbnail.rb +105 -0
  31. data/lib/paperclip/upfile.rb +62 -0
  32. data/lib/paperclip/version.rb +3 -0
  33. data/lib/paperclip.rb +478 -0
  34. data/lib/tasks/paperclip.rake +97 -0
  35. data/rails/init.rb +2 -0
  36. data/shoulda_macros/paperclip.rb +124 -0
  37. data/test/attachment_test.rb +1120 -0
  38. data/test/database.yml +4 -0
  39. data/test/fixtures/12k.png +0 -0
  40. data/test/fixtures/50x50.png +0 -0
  41. data/test/fixtures/5k.png +0 -0
  42. data/test/fixtures/animated.gif +0 -0
  43. data/test/fixtures/bad.png +1 -0
  44. data/test/fixtures/fog.yml +8 -0
  45. data/test/fixtures/s3.yml +8 -0
  46. data/test/fixtures/spaced file.png +0 -0
  47. data/test/fixtures/text.txt +1 -0
  48. data/test/fixtures/twopage.pdf +0 -0
  49. data/test/fixtures/uppercase.PNG +0 -0
  50. data/test/fog_test.rb +191 -0
  51. data/test/geometry_test.rb +206 -0
  52. data/test/helper.rb +152 -0
  53. data/test/integration_test.rb +654 -0
  54. data/test/interpolations_test.rb +195 -0
  55. data/test/iostream_test.rb +71 -0
  56. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  57. data/test/matchers/validate_attachment_content_type_matcher_test.rb +87 -0
  58. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  59. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  60. data/test/options_test.rb +68 -0
  61. data/test/paperclip_missing_attachment_styles_test.rb +80 -0
  62. data/test/paperclip_test.rb +329 -0
  63. data/test/processor_test.rb +10 -0
  64. data/test/storage/filesystem_test.rb +52 -0
  65. data/test/storage/s3_live_test.rb +51 -0
  66. data/test/storage/s3_test.rb +633 -0
  67. data/test/style_test.rb +180 -0
  68. data/test/thumbnail_test.rb +383 -0
  69. data/test/upfile_test.rb +53 -0
  70. metadata +243 -0
@@ -0,0 +1,329 @@
1
+ require './test/helper'
2
+
3
+ class PaperclipTest < Test::Unit::TestCase
4
+ context "Calling Paperclip.run" do
5
+ setup do
6
+ Cocaine::CommandLine.expects(:new).with("convert", "stuff").returns(stub(:run))
7
+ @original_command_line_path = Cocaine::CommandLine.path
8
+ end
9
+
10
+ teardown do
11
+ Cocaine::CommandLine.path = @original_command_line_path
12
+ end
13
+
14
+ should "run the command with Cocaine" do
15
+ Paperclip.run("convert", "stuff")
16
+ end
17
+
18
+ should "save Cocaine::CommandLine.path that set before" do
19
+ Cocaine::CommandLine.path = "/opt/my_app/bin"
20
+ Paperclip.run("convert", "stuff")
21
+ assert_equal [Cocaine::CommandLine.path].flatten.include?("/opt/my_app/bin"), true
22
+ end
23
+ end
24
+
25
+ context "Paperclip.each_instance_with_attachment" do
26
+ setup do
27
+ @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
28
+ d1 = Dummy.create(:avatar => @file)
29
+ d2 = Dummy.create
30
+ d3 = Dummy.create(:avatar => @file)
31
+ @expected = [d1, d3]
32
+ end
33
+ should "yield every instance of a model that has an attachment" do
34
+ actual = []
35
+ Paperclip.each_instance_with_attachment("Dummy", "avatar") do |instance|
36
+ actual << instance
37
+ end
38
+ assert_same_elements @expected, actual
39
+ end
40
+ end
41
+
42
+ should "raise when sent #processor and the name of a class that doesn't exist" do
43
+ assert_raises(NameError){ Paperclip.processor(:boogey_man) }
44
+ end
45
+
46
+ should "return a class when sent #processor and the name of a class under Paperclip" do
47
+ assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
48
+ end
49
+
50
+ should "get a class from a namespaced class name" do
51
+ class ::One; class Two; end; end
52
+ assert_equal ::One::Two, Paperclip.class_for("One::Two")
53
+ end
54
+
55
+ should "raise when class doesn't exist in specified namespace" do
56
+ class ::Three; end
57
+ class ::Four; end
58
+ assert_raise NameError do
59
+ Paperclip.class_for("Three::Four")
60
+ end
61
+ end
62
+
63
+ context "Attachments with clashing URLs should raise error" do
64
+ setup do
65
+ class Dummy2 < ActiveRecord::Base
66
+ include Paperclip::Glue
67
+ end
68
+ end
69
+
70
+ should "generate warning if attachment is redefined with the same url string" do
71
+ Paperclip.expects(:log).with("Duplicate URL for blah with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Dummy class")
72
+ Dummy.class_eval do
73
+ has_attached_file :blah
74
+ end
75
+ Dummy2.class_eval do
76
+ has_attached_file :blah
77
+ end
78
+ end
79
+ end
80
+
81
+ context "An ActiveRecord model with an 'avatar' attachment" do
82
+ setup do
83
+ rebuild_model :path => "tmp/:class/omg/:style.:extension"
84
+ @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
85
+ end
86
+
87
+ teardown { @file.close }
88
+
89
+ should "not error when trying to also create a 'blah' attachment" do
90
+ assert_nothing_raised do
91
+ Dummy.class_eval do
92
+ has_attached_file :blah
93
+ end
94
+ end
95
+ end
96
+
97
+ context "that is attr_protected" do
98
+ setup do
99
+ Dummy.class_eval do
100
+ attr_protected :avatar
101
+ end
102
+ @dummy = Dummy.new
103
+ end
104
+
105
+ should "not assign the avatar on mass-set" do
106
+ @dummy.attributes = { :other => "I'm set!",
107
+ :avatar => @file }
108
+
109
+ assert_equal "I'm set!", @dummy.other
110
+ assert ! @dummy.avatar?
111
+ end
112
+
113
+ should "still allow assigment on normal set" do
114
+ @dummy.other = "I'm set!"
115
+ @dummy.avatar = @file
116
+
117
+ assert_equal "I'm set!", @dummy.other
118
+ assert @dummy.avatar?
119
+ end
120
+ end
121
+
122
+ context "with a subclass" do
123
+ setup do
124
+ class ::SubDummy < Dummy; end
125
+ end
126
+
127
+ should "be able to use the attachment from the subclass" do
128
+ assert_nothing_raised do
129
+ @subdummy = SubDummy.create(:avatar => @file)
130
+ end
131
+ end
132
+
133
+ should "be able to see the attachment definition from the subclass's class" do
134
+ assert_equal "tmp/:class/omg/:style.:extension",
135
+ SubDummy.attachment_definitions[:avatar][:path]
136
+ end
137
+
138
+ teardown do
139
+ Object.send(:remove_const, "SubDummy") rescue nil
140
+ end
141
+ end
142
+
143
+ should "have an #avatar method" do
144
+ assert Dummy.new.respond_to?(:avatar)
145
+ end
146
+
147
+ should "have an #avatar= method" do
148
+ assert Dummy.new.respond_to?(:avatar=)
149
+ end
150
+
151
+ context "that is valid" do
152
+ setup do
153
+ @dummy = Dummy.new
154
+ @dummy.avatar = @file
155
+ end
156
+
157
+ should "be valid" do
158
+ assert @dummy.valid?
159
+ end
160
+ end
161
+
162
+ context "a validation with an if guard clause" do
163
+ setup do
164
+ Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
165
+ @dummy = Dummy.new
166
+ @dummy.stubs(:avatar_file_name).returns(nil)
167
+ end
168
+
169
+ should "attempt validation if the guard returns true" do
170
+ @dummy.expects(:foo).returns(true)
171
+ assert ! @dummy.valid?
172
+ end
173
+
174
+ should "not attempt validation if the guard returns false" do
175
+ @dummy.expects(:foo).returns(false)
176
+ assert @dummy.valid?
177
+ end
178
+ end
179
+
180
+ context "a validation with an unless guard clause" do
181
+ setup do
182
+ Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
183
+ @dummy = Dummy.new
184
+ @dummy.stubs(:avatar_file_name).returns(nil)
185
+ end
186
+
187
+ should "attempt validation if the guard returns true" do
188
+ @dummy.expects(:foo).returns(false)
189
+ assert ! @dummy.valid?
190
+ end
191
+
192
+ should "not attempt validation if the guard returns false" do
193
+ @dummy.expects(:foo).returns(true)
194
+ assert @dummy.valid?
195
+ end
196
+ end
197
+
198
+ should "not have Attachment in the ActiveRecord::Base namespace" do
199
+ assert_raises(NameError) do
200
+ ActiveRecord::Base::Attachment
201
+ end
202
+ end
203
+
204
+ def self.should_validate validation, options, valid_file, invalid_file
205
+ context "with #{validation} validation and #{options.inspect} options" do
206
+ setup do
207
+ rebuild_class
208
+ Dummy.send(:"validates_attachment_#{validation}", :avatar, options)
209
+ @dummy = Dummy.new
210
+ end
211
+ context "and assigning nil" do
212
+ setup do
213
+ @dummy.avatar = nil
214
+ @dummy.valid?
215
+ end
216
+ if validation == :presence
217
+ should "have an error on the attachment" do
218
+ assert @dummy.errors[:avatar_file_name]
219
+ end
220
+ else
221
+ should "not have an error on the attachment" do
222
+ assert @dummy.errors.blank?, @dummy.errors.full_messages.join(", ")
223
+ end
224
+ end
225
+ end
226
+ context "and assigned a valid file" do
227
+ setup do
228
+ @dummy.avatar = valid_file
229
+ @dummy.valid?
230
+ end
231
+ should "not have an error when assigned a valid file" do
232
+ assert_equal 0, @dummy.errors.size, @dummy.errors.full_messages.join(", ")
233
+ end
234
+ end
235
+ context "and assigned an invalid file" do
236
+ setup do
237
+ @dummy.avatar = invalid_file
238
+ @dummy.valid?
239
+ end
240
+ should "have an error when assigned a valid file" do
241
+ assert @dummy.errors.size > 0
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ [[:presence, {}, "5k.png", nil],
248
+ [:size, {:in => 1..10240}, "5k.png", "12k.png"],
249
+ [:size, {:less_than => 10240}, "5k.png", "12k.png"],
250
+ [:size, {:greater_than => 8096}, "12k.png", "5k.png"],
251
+ [:content_type, {:content_type => "image/png"}, "5k.png", "text.txt"],
252
+ [:content_type, {:content_type => "text/plain"}, "text.txt", "5k.png"],
253
+ [:content_type, {:content_type => %r{image/.*}}, "5k.png", "text.txt"]].each do |args|
254
+ validation, options, valid_file, invalid_file = args
255
+ valid_file &&= File.open(File.join(FIXTURES_DIR, valid_file), "rb")
256
+ invalid_file &&= File.open(File.join(FIXTURES_DIR, invalid_file), "rb")
257
+
258
+ should_validate validation, options, valid_file, invalid_file
259
+ end
260
+
261
+ context "with content_type validation and lambda message" do
262
+ context "and assigned an invalid file" do
263
+ setup do
264
+ Dummy.send(:"validates_attachment_content_type", :avatar, :content_type => %r{image/.*}, :message => lambda {'lambda content type message'})
265
+ @dummy = Dummy.new
266
+ @dummy.avatar &&= File.open(File.join(FIXTURES_DIR, "text.txt"), "rb")
267
+ @dummy.valid?
268
+ end
269
+
270
+ should "have a content type error message" do
271
+ assert [@dummy.errors[:avatar_content_type]].flatten.any?{|error| error =~ %r/lambda content type message/ }
272
+ end
273
+ end
274
+ end
275
+
276
+ context "with size validation and less_than 10240 option" do
277
+ context "and assigned an invalid file" do
278
+ setup do
279
+ Dummy.send(:"validates_attachment_size", :avatar, :less_than => 10240)
280
+ @dummy = Dummy.new
281
+ @dummy.avatar &&= File.open(File.join(FIXTURES_DIR, "12k.png"), "rb")
282
+ @dummy.valid?
283
+ end
284
+
285
+ should "have a file size min/max error message" do
286
+ assert [@dummy.errors[:avatar_file_size]].flatten.any?{|error| error =~ %r/between 0 and 10240 bytes/ }
287
+ end
288
+ end
289
+ end
290
+
291
+ context "with size validation and less_than 10240 option with lambda message" do
292
+ context "and assigned an invalid file" do
293
+ setup do
294
+ Dummy.send(:"validates_attachment_size", :avatar, :less_than => 10240, :message => lambda {'lambda between 0 and 10240 bytes'})
295
+ @dummy = Dummy.new
296
+ @dummy.avatar &&= File.open(File.join(FIXTURES_DIR, "12k.png"), "rb")
297
+ @dummy.valid?
298
+ end
299
+
300
+ should "have a file size min/max error message" do
301
+ assert [@dummy.errors[:avatar_file_size]].flatten.any?{|error| error =~ %r/lambda between 0 and 10240 bytes/ }
302
+ end
303
+ end
304
+ end
305
+
306
+ end
307
+
308
+ context "configuring a custom processor" do
309
+ setup do
310
+ @freedom_processor = Class.new do
311
+ def make(file, options = {}, attachment = nil)
312
+ file
313
+ end
314
+ end.new
315
+
316
+ Paperclip.configure do |config|
317
+ config.register_processor(:freedom, @freedom_processor)
318
+ end
319
+ end
320
+
321
+ should "be able to find the custom processor" do
322
+ assert_equal @freedom_processor, Paperclip.processor(:freedom)
323
+ end
324
+
325
+ teardown do
326
+ Paperclip.clear_processors!
327
+ end
328
+ end
329
+ end
@@ -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,52 @@
1
+ require './test/helper'
2
+
3
+ class FileSystemTest < Test::Unit::TestCase
4
+ context "Filesystem" do
5
+ setup do
6
+ rebuild_model :styles => { :thumbnail => "25x25#" }
7
+ @dummy = Dummy.create!
8
+
9
+ @dummy.avatar = File.open(File.join(File.dirname(__FILE__), "..", "fixtures", "5k.png"))
10
+ end
11
+
12
+ should "allow file assignment" do
13
+ assert @dummy.save
14
+ end
15
+
16
+ should "store the original" do
17
+ @dummy.save
18
+ assert File.exists?(@dummy.avatar.path)
19
+ end
20
+
21
+ should "store the thumbnail" do
22
+ @dummy.save
23
+ assert File.exists?(@dummy.avatar.path(:thumbnail))
24
+ end
25
+
26
+ should "clean up file objects" do
27
+ File.stubs(:exist?).returns(true)
28
+ Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
29
+ Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
30
+
31
+ @dummy.save!
32
+ end
33
+
34
+ context "with file that has space in file name" do
35
+ setup do
36
+ rebuild_model :styles => { :thumbnail => "25x25#" }
37
+ @dummy = Dummy.create!
38
+
39
+ @dummy.avatar = File.open(File.join(File.dirname(__FILE__), "..", "fixtures", "spaced file.png"))
40
+ @dummy.save
41
+ end
42
+
43
+ should "store the file" do
44
+ assert File.exists?(@dummy.avatar.path)
45
+ end
46
+
47
+ should "return an escaped version of URL" do
48
+ assert_match /\/spaced%20file\.png/, @dummy.avatar.url
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,51 @@
1
+ require './test/helper'
2
+ require 'aws/s3'
3
+
4
+ unless ENV["S3_TEST_BUCKET"].blank?
5
+ class S3LiveTest < Test::Unit::TestCase
6
+ context "Using S3 for real, an attachment with S3 storage" do
7
+ setup do
8
+ rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
9
+ :storage => :s3,
10
+ :bucket => ENV["S3_TEST_BUCKET"],
11
+ :path => ":class/:attachment/:id/:style.:extension",
12
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "s3.yml"))
13
+
14
+ Dummy.delete_all
15
+ @dummy = Dummy.new
16
+ end
17
+
18
+ should "be extended by the S3 module" do
19
+ assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
20
+ end
21
+
22
+ context "when assigned" do
23
+ setup do
24
+ @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
25
+ @dummy.avatar = @file
26
+ end
27
+
28
+ teardown { @file.close }
29
+
30
+ should "still return a Tempfile when sent #to_file" do
31
+ assert_equal Paperclip::Tempfile, @dummy.avatar.to_file.class
32
+ end
33
+
34
+ context "and saved" do
35
+ setup do
36
+ @dummy.save
37
+ end
38
+
39
+ should "be on S3" do
40
+ assert true
41
+ end
42
+
43
+ should "generate a tempfile with the right name" do
44
+ file = @dummy.avatar.to_file
45
+ assert_match /^original.*\.png$/, File.basename(file.path)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end