paperclip 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ This is not an image.
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ require 'tempfile'
6
+
7
+ require 'active_record'
8
+ begin
9
+ require 'ruby-debug'
10
+ rescue LoadError
11
+ puts "ruby-debug not loaded"
12
+ end
13
+
14
+ ROOT = File.join(File.dirname(__FILE__), '..')
15
+ RAILS_ROOT = ROOT
16
+
17
+ $LOAD_PATH << File.join(ROOT, 'lib')
18
+ $LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
19
+
20
+ require File.join(ROOT, 'lib', 'paperclip.rb')
21
+
22
+ ENV['RAILS_ENV'] ||= 'test'
23
+
24
+ FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
25
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
26
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
27
+ ActiveRecord::Base.establish_connection(config[ENV['RAILS_ENV'] || 'test'])
28
+
29
+ def rebuild_model options = {}
30
+ ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
31
+ table.column :other, :string
32
+ table.column :avatar_file_name, :string
33
+ table.column :avatar_content_type, :string
34
+ table.column :avatar_file_size, :integer
35
+ end
36
+
37
+ ActiveRecord::Base.send(:include, Paperclip)
38
+ Object.send(:remove_const, "Dummy") rescue nil
39
+ Object.const_set("Dummy", Class.new(ActiveRecord::Base))
40
+ Dummy.class_eval do
41
+ include Paperclip
42
+ has_attached_file :avatar, options
43
+ end
44
+ end
@@ -0,0 +1,2 @@
1
+ access_key_id: 11196XQ35WGRKEVQN782
2
+ secret_access_key: TczVRadcH5sealaWUMpbY/Hnex90iCmJ3LDM5w74
@@ -0,0 +1,207 @@
1
+ require 'test/helper'
2
+
3
+ class Dummy
4
+ # This is a dummy class
5
+ end
6
+
7
+ class AttachmentTest < Test::Unit::TestCase
8
+ context "Attachment default_options" do
9
+ setup do
10
+ rebuild_model
11
+ @old_default_options = Paperclip::Attachment.default_options.dup
12
+ @new_default_options = @old_default_options.merge({
13
+ :path => "argle/bargle",
14
+ :url => "fooferon",
15
+ :default_url => "not here.png"
16
+ })
17
+ end
18
+
19
+ teardown do
20
+ Paperclip::Attachment.default_options.merge! @old_default_options
21
+ end
22
+
23
+ should "be overrideable" do
24
+ Paperclip::Attachment.default_options.merge!(@new_default_options)
25
+ @new_default_options.keys.each do |key|
26
+ assert_equal @new_default_options[key],
27
+ Paperclip::Attachment.default_options[key]
28
+ end
29
+ end
30
+
31
+ context "on an Attachment" do
32
+ setup do
33
+ @dummy = Dummy.new
34
+ @attachment = @dummy.avatar
35
+ end
36
+
37
+ Paperclip::Attachment.default_options.keys.each do |key|
38
+ should "be the default_options for #{key}" do
39
+ assert_equal @old_default_options[key],
40
+ @attachment.instance_variable_get("@#{key}"),
41
+ key
42
+ end
43
+ end
44
+
45
+ context "when redefined" do
46
+ setup do
47
+ Paperclip::Attachment.default_options.merge!(@new_default_options)
48
+ @dummy = Dummy.new
49
+ @attachment = @dummy.avatar
50
+ end
51
+
52
+ Paperclip::Attachment.default_options.keys.each do |key|
53
+ should "be the new default_options for #{key}" do
54
+ assert_equal @new_default_options[key],
55
+ @attachment.instance_variable_get("@#{key}"),
56
+ key
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ context "An attachment with similarly named interpolations" do
64
+ setup do
65
+ rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
66
+ @dummy = Dummy.new
67
+ @dummy.stubs(:id).returns(1024)
68
+ @file = File.new(File.join(File.dirname(__FILE__),
69
+ "fixtures",
70
+ "5k.png"))
71
+ @dummy.avatar = @file
72
+ end
73
+
74
+ should "make sure that they are interpolated correctly" do
75
+ assert_equal "1024.omg/1024-bbq/:idwhat/000/001/024.wtf", @dummy.avatar.path
76
+ end
77
+ end
78
+
79
+ context "An attachment" do
80
+ setup do
81
+ Paperclip::Attachment.default_options.merge!({
82
+ :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
83
+ })
84
+ FileUtils.rm_rf("tmp")
85
+ @instance = stub
86
+ @instance.stubs(:id).returns(41)
87
+ @instance.stubs(:class).returns(Dummy)
88
+ @instance.stubs(:[]).with(:test_file_name).returns("5k.png")
89
+ @instance.stubs(:[]).with(:test_content_type).returns("image/png")
90
+ @instance.stubs(:[]).with(:test_file_size).returns(12345)
91
+ @attachment = Paperclip::Attachment.new(:test,
92
+ @instance)
93
+ @file = File.new(File.join(File.dirname(__FILE__),
94
+ "fixtures",
95
+ "5k.png"))
96
+ end
97
+
98
+ should "return its default_url when no file assigned" do
99
+ assert @attachment.file.nil?
100
+ assert_equal "/tests/original/missing.png", @attachment.url
101
+ assert_equal "/tests/blah/missing.png", @attachment.url(:blah)
102
+ end
103
+
104
+ context "when expecting three styles" do
105
+ setup do
106
+ styles = {:styles => { :large => ["400x400", :png],
107
+ :medium => ["100x100", :gif],
108
+ :small => ["32x32#", :jpg]}}
109
+ @attachment = Paperclip::Attachment.new(:test,
110
+ @instance,
111
+ styles)
112
+ end
113
+
114
+ context "and assigned a file" do
115
+ setup do
116
+ @instance.expects(:[]=).with(:test_file_name,
117
+ File.basename(@file.path))
118
+ @instance.expects(:[]=).with(:test_content_type, "image/png")
119
+ @instance.expects(:[]=).with(:test_file_size, @file.size)
120
+ @instance.expects(:[]=).with(:test_file_name, nil)
121
+ @instance.expects(:[]=).with(:test_content_type, nil)
122
+ @instance.expects(:[]=).with(:test_file_size, nil)
123
+ @attachment.assign(@file)
124
+ end
125
+
126
+ should "return the real url" do
127
+ assert @attachment.file
128
+ assert_equal "/tests/41/original/5k.png", @attachment.url
129
+ assert_equal "/tests/41/blah/5k.png", @attachment.url(:blah)
130
+ end
131
+
132
+ should "be dirty" do
133
+ assert @attachment.dirty?
134
+ end
135
+
136
+ should "have its image and attachments as tempfiles" do
137
+ [nil, :large, :medium, :small].each do |style|
138
+ assert File.exists?(@attachment.to_io(style))
139
+ end
140
+ end
141
+
142
+ context "and saved" do
143
+ setup do
144
+ @attachment.save
145
+ end
146
+
147
+ should "commit the files to disk" do
148
+ [nil, :large, :medium, :small].each do |style|
149
+ io = @attachment.to_io(style)
150
+ assert File.exists?(io)
151
+ assert ! io.is_a?(::Tempfile)
152
+ end
153
+ end
154
+
155
+ should "save the files as the right formats and sizes" do
156
+ [[:large, 400, 61, "PNG"],
157
+ [:medium, 100, 15, "GIF"],
158
+ [:small, 32, 32, "JPEG"]].each do |style|
159
+ cmd = "identify -format '%w %h %b %m' " +
160
+ "#{@attachment.to_io(style.first).path}"
161
+ out = `#{cmd}`
162
+ width, height, size, format = out.split(" ")
163
+ assert_equal style[1].to_s, width.to_s
164
+ assert_equal style[2].to_s, height.to_s
165
+ assert_equal style[3].to_s, format.to_s
166
+ end
167
+ end
168
+
169
+ should "have #file be equal #to_io(:original)" do
170
+ assert_equal @attachment.file, @attachment.to_io(:original)
171
+ end
172
+
173
+ should "still have its #file attribute not be nil" do
174
+ assert ! @attachment.file.nil?
175
+ end
176
+
177
+ context "and deleted" do
178
+ setup do
179
+ @existing_names = @attachment.styles.keys.collect do |style|
180
+ @attachment.path(style)
181
+ end
182
+ @instance.expects(:[]=).with(:test_file_name, nil)
183
+ @instance.expects(:[]=).with(:test_content_type, nil)
184
+ @instance.expects(:[]=).with(:test_file_size, nil)
185
+ @attachment.assign nil
186
+ @attachment.save
187
+ end
188
+
189
+ should "delete the files" do
190
+ @existing_names.each{|f| assert ! File.exists?(f) }
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ context "when trying a nonexistant storage type" do
198
+ setup do
199
+ rebuild_model :storage => :not_here
200
+ end
201
+
202
+ should "not be able to find the module" do
203
+ assert_raise(NameError){ Dummy.new.avatar }
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,142 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'paperclip', 'geometry.rb')
6
+
7
+ class GeometryTest < Test::Unit::TestCase
8
+ context "Paperclip::Geometry" do
9
+ should "correctly report its given dimensions" do
10
+ assert @geo = Paperclip::Geometry.new(1024, 768)
11
+ assert_equal 1024, @geo.width
12
+ assert_equal 768, @geo.height
13
+ end
14
+
15
+ should "correctly create a square if the height dimension is missing" do
16
+ assert @geo = Paperclip::Geometry.new(1024)
17
+ assert_equal 1024, @geo.width
18
+ assert_equal 1024, @geo.height
19
+ end
20
+
21
+ should "correctly create a square if the width dimension is missing" do
22
+ assert @geo = Paperclip::Geometry.new(nil, 768)
23
+ assert_equal 768, @geo.width
24
+ assert_equal 768, @geo.height
25
+ end
26
+
27
+ should "be generated from a WxH-formatted string" do
28
+ assert @geo = Paperclip::Geometry.parse("800x600")
29
+ assert_equal 800, @geo.width
30
+ assert_equal 600, @geo.height
31
+ end
32
+
33
+ should "be generated from a xH-formatted string" do
34
+ assert @geo = Paperclip::Geometry.parse("x600")
35
+ assert_equal 600, @geo.width
36
+ assert_equal 600, @geo.height
37
+ end
38
+
39
+ should "be generated from a Wx-formatted string" do
40
+ assert @geo = Paperclip::Geometry.parse("800x")
41
+ assert_equal 800, @geo.width
42
+ assert_equal 800, @geo.height
43
+ end
44
+
45
+ should "ensure the modifier is nil if only one dimension present" do
46
+ assert @geo = Paperclip::Geometry.parse("123x")
47
+ assert_nil @geo.modifier
48
+ end
49
+
50
+ should "ensure the modifier is nil if not present" do
51
+ assert @geo = Paperclip::Geometry.parse("123x456")
52
+ assert_nil @geo.modifier
53
+ end
54
+
55
+ ['>', '<', '#', '@', '%', '^', '!'].each do |mod|
56
+ should "ensure the modifier #{mod} is preserved" do
57
+ assert @geo = Paperclip::Geometry.parse("123x456#{mod}")
58
+ assert_equal mod, @geo.modifier
59
+ end
60
+ end
61
+
62
+ should "make sure the modifier gets passed during transformation_to" do
63
+ assert @src = Paperclip::Geometry.parse("123x456")
64
+ assert @dst = Paperclip::Geometry.parse("123x456>")
65
+ assert_equal "123x456>", @src.transformation_to(@dst).to_s
66
+ end
67
+
68
+ should "be generated from a file" do
69
+ file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
70
+ file = File.new(file)
71
+ assert_nothing_raised{ @geo = Paperclip::Geometry.from_file(file) }
72
+ assert @geo.height > 0
73
+ assert @geo.width > 0
74
+ end
75
+
76
+ should "be generated from a file path" do
77
+ file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
78
+ assert_nothing_raised{ @geo = Paperclip::Geometry.from_file(file) }
79
+ assert @geo.height > 0
80
+ assert @geo.width > 0
81
+ end
82
+
83
+ should "not generate from a bad file" do
84
+ file = "/home/This File Does Not Exist.omg"
85
+ assert_raise(Errno::ENOENT){ @geo = Paperclip::Geometry.from_file(file) }
86
+ end
87
+
88
+ [['vertical', 900, 1440, true, false, false, 1440, 900, 0.625],
89
+ ['horizontal', 1024, 768, false, true, false, 1024, 768, 1.3333],
90
+ ['square', 100, 100, false, false, true, 100, 100, 1]].each do |args|
91
+ context "performing calculations on a #{args[0]} viewport" do
92
+ setup do
93
+ @geo = Paperclip::Geometry.new(args[1], args[2])
94
+ end
95
+
96
+ should "#{args[3] ? "" : "not"} be vertical" do
97
+ assert_equal args[3], @geo.vertical?
98
+ end
99
+
100
+ should "#{args[4] ? "" : "not"} be horizontal" do
101
+ assert_equal args[4], @geo.horizontal?
102
+ end
103
+
104
+ should "#{args[5] ? "" : "not"} be square" do
105
+ assert_equal args[5], @geo.square?
106
+ end
107
+
108
+ should "report that #{args[6]} is the larger dimension" do
109
+ assert_equal args[6], @geo.larger
110
+ end
111
+
112
+ should "report that #{args[7]} is the smaller dimension" do
113
+ assert_equal args[7], @geo.smaller
114
+ end
115
+
116
+ should "have an aspect ratio of #{args[8]}" do
117
+ assert_in_delta args[8], @geo.aspect, 0.0001
118
+ end
119
+ end
120
+ end
121
+
122
+ [[ [1000, 100], [64, 64], "x64", "64x64+288+0" ],
123
+ [ [100, 1000], [50, 950], "x950", "50x950+22+0" ],
124
+ [ [100, 1000], [50, 25], "50x", "50x25+0+237" ]]. each do |args|
125
+ context "of #{args[0].inspect} and given a Geometry #{args[1].inspect} and sent transform_to" do
126
+ setup do
127
+ @geo = Paperclip::Geometry.new(*args[0])
128
+ @dst = Paperclip::Geometry.new(*args[1])
129
+ @scale, @crop = @geo.transformation_to @dst, true
130
+ end
131
+
132
+ should "be able to return the correct scaling transformation geometry #{args[2]}" do
133
+ assert_equal args[2], @scale
134
+ end
135
+
136
+ should "be able to return the correct crop transformation geometry #{args[3]}" do
137
+ assert_equal args[3], @crop
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,238 @@
1
+ require 'test/helper.rb'
2
+
3
+ class IntegrationTest < Test::Unit::TestCase
4
+ context "A model with a filesystem attachment" do
5
+ setup do
6
+ rebuild_model :styles => { :large => "300x300>",
7
+ :medium => "100x100",
8
+ :thumb => ["32x32#", :gif] },
9
+ :default_style => :medium,
10
+ :url => "/:attachment/:class/:style/:id/:basename.:extension",
11
+ :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
12
+ @dummy = Dummy.new
13
+ @file = File.new(File.join(FIXTURES_DIR, "5k.png"))
14
+ @bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"))
15
+
16
+ assert @dummy.avatar = @file
17
+ assert @dummy.valid?
18
+ assert @dummy.save
19
+ end
20
+
21
+ should "write and delete its files" do
22
+ [["100x15", nil],
23
+ ["434x66", :original],
24
+ ["300x46", :large],
25
+ ["100x15", :medium],
26
+ ["32x32", :thumb]].each do |geo, style|
27
+ cmd = %Q[identify -format "%wx%h" #{@dummy.avatar.to_file(style).path}]
28
+ assert_equal geo, `#{cmd}`.chomp, cmd
29
+ end
30
+
31
+ saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s).path }
32
+
33
+ @d2 = Dummy.find(@dummy.id)
34
+ assert_equal "100x15", `identify -format "%wx%h" #{@d2.avatar.to_file.path}`.chomp
35
+ assert_equal "434x66", `identify -format "%wx%h" #{@d2.avatar.to_file(:original).path}`.chomp
36
+ assert_equal "300x46", `identify -format "%wx%h" #{@d2.avatar.to_file(:large).path}`.chomp
37
+ assert_equal "100x15", `identify -format "%wx%h" #{@d2.avatar.to_file(:medium).path}`.chomp
38
+ assert_equal "32x32", `identify -format "%wx%h" #{@d2.avatar.to_file(:thumb).path}`.chomp
39
+
40
+ @dummy.avatar = "not a valid file but not nil"
41
+ assert_equal File.basename(@file.path), @dummy.avatar_file_name
42
+ assert @dummy.valid?
43
+ assert @dummy.save
44
+
45
+ saved_paths.each do |p|
46
+ assert File.exists?(p)
47
+ end
48
+
49
+ @dummy.avatar = nil
50
+ assert_nil @dummy.avatar_file_name
51
+ assert @dummy.valid?
52
+ assert @dummy.save
53
+
54
+ saved_paths.each do |p|
55
+ assert ! File.exists?(p)
56
+ end
57
+
58
+ @d2 = Dummy.find(@dummy.id)
59
+ assert_nil @d2.avatar_file_name
60
+ end
61
+
62
+ should "work exactly the same when new as when reloaded" do
63
+ @d2 = Dummy.find(@dummy.id)
64
+
65
+ assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
66
+ [:thumb, :medium, :large, :original].each do |style|
67
+ assert_equal @dummy.avatar.to_file(style).path, @d2.avatar.to_file(style).path
68
+ end
69
+
70
+ saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s).path }
71
+
72
+ @d2.avatar = nil
73
+ assert @d2.save
74
+
75
+ saved_paths.each do |p|
76
+ assert ! File.exists?(p)
77
+ end
78
+ end
79
+
80
+ should "know the difference between good files, bad files, not files, and nil" do
81
+ expected = @dummy.avatar.file
82
+ @dummy.avatar = "not a file"
83
+ assert @dummy.valid?
84
+ assert_equal expected.path, @dummy.avatar.file.path
85
+
86
+ @dummy.avatar = @bad_file
87
+ assert ! @dummy.valid?
88
+ @dummy.avatar = nil
89
+ assert @dummy.valid?
90
+
91
+ Dummy.validates_attachment_presence :avatar
92
+ @d2 = Dummy.find(@dummy.id)
93
+ @d2.avatar = @file
94
+ assert @d2.valid?
95
+ @d2.avatar = @bad_file
96
+ assert ! @d2.valid?
97
+ @d2.avatar = nil
98
+ assert ! @d2.valid?
99
+ end
100
+
101
+ should "be able to reload without saving an not have the file disappear" do
102
+ @dummy.avatar = @file
103
+ assert @dummy.save
104
+ @dummy.avatar = nil
105
+ assert_nil @dummy.avatar_file_name
106
+ @dummy.reload
107
+ assert_equal "5k.png", @dummy.avatar_file_name
108
+ end
109
+ end
110
+
111
+ if ENV['S3_TEST_BUCKET']
112
+ def s3_files_for attachment
113
+ [:thumb, :medium, :large, :original].inject({}) do |files, style|
114
+ data = `curl '#{attachment.url(style)}' 2>/dev/null`.chomp
115
+ t = Tempfile.new("paperclip-test")
116
+ t.write(data)
117
+ t.rewind
118
+ files[style] = t
119
+ files
120
+ end
121
+ end
122
+
123
+ context "A model with an S3 attachment" do
124
+ setup do
125
+ rebuild_model :styles => { :large => "300x300>",
126
+ :medium => "100x100",
127
+ :thumb => ["32x32#", :gif] },
128
+ :storage => :s3,
129
+ # :s3_options => {:logger => Logger.new(StringIO.new)},
130
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml")),
131
+ :default_style => :medium,
132
+ :bucket => ENV['S3_TEST_BUCKET'],
133
+ :path => ":class/:attachment/:id/:style/:basename.:extension"
134
+ @dummy = Dummy.new
135
+ @file = File.new(File.join(FIXTURES_DIR, "5k.png"))
136
+ @bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"))
137
+
138
+ assert @dummy.avatar = @file
139
+ assert @dummy.valid?
140
+ assert @dummy.save
141
+
142
+ @files_on_s3 = s3_files_for @dummy.avatar
143
+ end
144
+
145
+ should "write and delete its files" do
146
+ [["434x66", :original],
147
+ ["300x46", :large],
148
+ ["100x15", :medium],
149
+ ["32x32", :thumb]].each do |geo, style|
150
+ cmd = %Q[identify -format "%wx%h" #{@files_on_s3[style].path}]
151
+ assert_equal geo, `#{cmd}`.chomp, cmd
152
+ end
153
+
154
+ @d2 = Dummy.find(@dummy.id)
155
+ @d2_files = s3_files_for @d2.avatar
156
+ [["434x66", :original],
157
+ ["300x46", :large],
158
+ ["100x15", :medium],
159
+ ["32x32", :thumb]].each do |geo, style|
160
+ cmd = %Q[identify -format "%wx%h" #{@d2_files[style].path}]
161
+ assert_equal geo, `#{cmd}`.chomp, cmd
162
+ end
163
+
164
+ @dummy.avatar = "not a valid file but not nil"
165
+ assert_equal File.basename(@file.path), @dummy.avatar_file_name
166
+ assert @dummy.valid?
167
+ assert @dummy.save
168
+
169
+ saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
170
+
171
+ saved_keys.each do |key|
172
+ assert key.exists?
173
+ end
174
+
175
+ @dummy.avatar = nil
176
+ assert_nil @dummy.avatar_file_name
177
+ assert @dummy.valid?
178
+ assert @dummy.save
179
+
180
+ saved_keys.each do |key|
181
+ assert ! key.exists?
182
+ end
183
+
184
+ @d2 = Dummy.find(@dummy.id)
185
+ assert_nil @d2.avatar_file_name
186
+ end
187
+
188
+ should "work exactly the same when new as when reloaded" do
189
+ @d2 = Dummy.find(@dummy.id)
190
+
191
+ assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
192
+ [:thumb, :medium, :large, :original].each do |style|
193
+ assert_equal @dummy.avatar.to_file(style).to_s, @d2.avatar.to_file(style).to_s
194
+ end
195
+
196
+ saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
197
+
198
+ @d2.avatar = nil
199
+ assert @d2.save
200
+
201
+ saved_keys.each do |key|
202
+ assert ! key.exists?
203
+ end
204
+ end
205
+
206
+ should "know the difference between good files, bad files, not files, and nil" do
207
+ expected = @dummy.avatar.file
208
+ @dummy.avatar = "not a file"
209
+ assert @dummy.valid?
210
+ assert_equal expected, @dummy.avatar.file
211
+
212
+ @dummy.avatar = @bad_file
213
+ assert ! @dummy.valid?
214
+ @dummy.avatar = nil
215
+ assert @dummy.valid?
216
+
217
+ Dummy.validates_attachment_presence :avatar
218
+ @d2 = Dummy.find(@dummy.id)
219
+ @d2.avatar = @file
220
+ assert @d2.valid?
221
+ @d2.avatar = @bad_file
222
+ assert ! @d2.valid?
223
+ @d2.avatar = nil
224
+ assert ! @d2.valid?
225
+ end
226
+
227
+ should "be able to reload without saving an not have the file disappear" do
228
+ @dummy.avatar = @file
229
+ assert @dummy.save
230
+ @dummy.avatar = nil
231
+ assert_nil @dummy.avatar_file_name
232
+ @dummy.reload
233
+ assert_equal "5k.png", @dummy.avatar_file_name
234
+ end
235
+ end
236
+ end
237
+ end
238
+