mender_paperclip 2.4.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 (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