bulldog 0.0.1
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.
- data/.gitignore +2 -0
- data/DESCRIPTION.txt +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/bulldog.gemspec +157 -0
- data/lib/bulldog.rb +95 -0
- data/lib/bulldog/attachment.rb +49 -0
- data/lib/bulldog/attachment/base.rb +167 -0
- data/lib/bulldog/attachment/has_dimensions.rb +94 -0
- data/lib/bulldog/attachment/image.rb +63 -0
- data/lib/bulldog/attachment/maybe.rb +229 -0
- data/lib/bulldog/attachment/none.rb +37 -0
- data/lib/bulldog/attachment/pdf.rb +63 -0
- data/lib/bulldog/attachment/unknown.rb +11 -0
- data/lib/bulldog/attachment/video.rb +143 -0
- data/lib/bulldog/error.rb +5 -0
- data/lib/bulldog/has_attachment.rb +214 -0
- data/lib/bulldog/interpolation.rb +73 -0
- data/lib/bulldog/missing_file.rb +12 -0
- data/lib/bulldog/processor.rb +5 -0
- data/lib/bulldog/processor/argument_tree.rb +116 -0
- data/lib/bulldog/processor/base.rb +124 -0
- data/lib/bulldog/processor/ffmpeg.rb +172 -0
- data/lib/bulldog/processor/image_magick.rb +134 -0
- data/lib/bulldog/processor/one_shot.rb +19 -0
- data/lib/bulldog/reflection.rb +234 -0
- data/lib/bulldog/saved_file.rb +19 -0
- data/lib/bulldog/stream.rb +186 -0
- data/lib/bulldog/style.rb +38 -0
- data/lib/bulldog/style_set.rb +101 -0
- data/lib/bulldog/tempfile.rb +28 -0
- data/lib/bulldog/util.rb +92 -0
- data/lib/bulldog/validations.rb +68 -0
- data/lib/bulldog/vector2.rb +18 -0
- data/rails/init.rb +9 -0
- data/script/console +8 -0
- data/spec/data/empty.txt +0 -0
- data/spec/data/test.jpg +0 -0
- data/spec/data/test.mov +0 -0
- data/spec/data/test.pdf +0 -0
- data/spec/data/test.png +0 -0
- data/spec/data/test2.jpg +0 -0
- data/spec/helpers/image_creation.rb +8 -0
- data/spec/helpers/temporary_directory.rb +25 -0
- data/spec/helpers/temporary_models.rb +76 -0
- data/spec/helpers/temporary_values.rb +102 -0
- data/spec/helpers/test_upload_files.rb +108 -0
- data/spec/helpers/time_travel.rb +20 -0
- data/spec/integration/data/test.jpg +0 -0
- data/spec/integration/lifecycle_hooks_spec.rb +213 -0
- data/spec/integration/processing_image_attachments.rb +72 -0
- data/spec/integration/processing_video_attachments_spec.rb +82 -0
- data/spec/integration/saving_an_attachment_spec.rb +31 -0
- data/spec/matchers/file_operations.rb +159 -0
- data/spec/spec_helper.rb +76 -0
- data/spec/unit/attachment/base_spec.rb +311 -0
- data/spec/unit/attachment/image_spec.rb +128 -0
- data/spec/unit/attachment/maybe_spec.rb +126 -0
- data/spec/unit/attachment/pdf_spec.rb +137 -0
- data/spec/unit/attachment/video_spec.rb +176 -0
- data/spec/unit/attachment_spec.rb +61 -0
- data/spec/unit/has_attachment_spec.rb +700 -0
- data/spec/unit/interpolation_spec.rb +108 -0
- data/spec/unit/processor/argument_tree_spec.rb +159 -0
- data/spec/unit/processor/ffmpeg_spec.rb +467 -0
- data/spec/unit/processor/image_magick_spec.rb +260 -0
- data/spec/unit/processor/one_shot_spec.rb +70 -0
- data/spec/unit/reflection_spec.rb +338 -0
- data/spec/unit/stream_spec.rb +234 -0
- data/spec/unit/style_set_spec.rb +44 -0
- data/spec/unit/style_spec.rb +51 -0
- data/spec/unit/validations_spec.rb +491 -0
- data/spec/unit/vector2_spec.rb +27 -0
- data/tasks/bulldog_tasks.rake +4 -0
- metadata +193 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
module TemporaryValues
|
2
|
+
def self.included(mod)
|
3
|
+
mod.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
#
|
7
|
+
# Use +value+ for the value of the constant +mod::name+ for the
|
8
|
+
# duration of the block.
|
9
|
+
#
|
10
|
+
def with_temporary_constant_value(mod, name, value)
|
11
|
+
save_and_set_constant(mod, name, value)
|
12
|
+
yield
|
13
|
+
ensure
|
14
|
+
restore_constant(mod, name)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Use +value+ for the value of the +name+ attribute of the given
|
19
|
+
# +object+ for the duration of the block.
|
20
|
+
#
|
21
|
+
def with_temporary_attribute_value(object, name, value)
|
22
|
+
save_and_set_attribute(object, name, value)
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
restore_attribute(object, name)
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
#
|
30
|
+
# Use +value+ for the value of the constant +mod::name+ for the
|
31
|
+
# duration of each example in this example group.
|
32
|
+
#
|
33
|
+
# If the value should be recalculated for each example, pass a
|
34
|
+
# block instead of a value argument.
|
35
|
+
#
|
36
|
+
def use_temporary_constant_value(mod, name, value=nil, &block)
|
37
|
+
before do
|
38
|
+
value = block ? instance_eval(&block) : value
|
39
|
+
save_and_set_constant(mod, name, value)
|
40
|
+
end
|
41
|
+
after do
|
42
|
+
restore_constant(mod, name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Use +value+ for the value of the +name+ attribute of the given
|
48
|
+
# +object+ for the duration of each example in this example group.
|
49
|
+
#
|
50
|
+
# If the value should be recalculated for each example, pass a
|
51
|
+
# block instead of a value argument.
|
52
|
+
#
|
53
|
+
def use_temporary_attribute_value(object, name, value=nil, &block)
|
54
|
+
before do
|
55
|
+
value = block ? instance_eval(&block) : value
|
56
|
+
save_and_set_attribute(object, name, value)
|
57
|
+
end
|
58
|
+
after do
|
59
|
+
restore_attribute(object, name)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private # ---------------------------------------------------------
|
65
|
+
|
66
|
+
UNDEFINED = Object.new
|
67
|
+
|
68
|
+
def original_attribute_values
|
69
|
+
@original_attribute_values ||= Hash.new{|h,k| h[k] = Hash.new{|h2,k2| h2[k2] = {}}}
|
70
|
+
end
|
71
|
+
|
72
|
+
def save_and_set_attribute(object, name, value)
|
73
|
+
original_attribute_values[object.__id__][name] = object.send(name)
|
74
|
+
object.send("#{name}=", value)
|
75
|
+
end
|
76
|
+
|
77
|
+
def restore_attribute(object, name)
|
78
|
+
value = original_attribute_values[object.__id__].delete(name)
|
79
|
+
object.send("#{name}=", value)
|
80
|
+
end
|
81
|
+
|
82
|
+
def original_constant_values
|
83
|
+
@original_constant_values ||= Hash.new{|h,k| h[k] = Hash.new{|h2,k2| h2[k2] = {}}}
|
84
|
+
end
|
85
|
+
|
86
|
+
def save_and_set_constant(mod, name, value)
|
87
|
+
if mod.const_defined?(name)
|
88
|
+
original_constant_values[mod.name][name] = mod.send(:remove_const, name)
|
89
|
+
else
|
90
|
+
original_constant_values[mod.name][name] = UNDEFINED
|
91
|
+
end
|
92
|
+
mod.const_set(name, value)
|
93
|
+
end
|
94
|
+
|
95
|
+
def restore_constant(mod, name)
|
96
|
+
mod.send(:remove_const, name)
|
97
|
+
original_value = original_constant_values[mod.name].delete(name)
|
98
|
+
unless original_value.equal?(UNDEFINED)
|
99
|
+
mod.const_set(name, original_value)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module TestUploadFiles
|
2
|
+
def self.included(mod)
|
3
|
+
mod.before{init_test_upload_files}
|
4
|
+
mod.after{close_test_upload_files}
|
5
|
+
end
|
6
|
+
|
7
|
+
def autoclose(file)
|
8
|
+
@files_to_close << file
|
9
|
+
file
|
10
|
+
end
|
11
|
+
|
12
|
+
def small_uploaded_file(path=unused_temp_path, test_file='test.jpg')
|
13
|
+
content = content_for_uploaded_file(test_file)
|
14
|
+
io = ActionController::UploadedStringIO.new(content)
|
15
|
+
io.original_path = path
|
16
|
+
io.content_type = Rack::Mime::MIME_TYPES[File.extname(path)]
|
17
|
+
io
|
18
|
+
end
|
19
|
+
|
20
|
+
def large_uploaded_file(path=unused_temp_path, test_file='test.jpg')
|
21
|
+
content = content_for_uploaded_file(test_file)
|
22
|
+
file = ActionController::UploadedTempfile.new(path)
|
23
|
+
file.write(content)
|
24
|
+
file.rewind
|
25
|
+
file.original_path = path
|
26
|
+
file.content_type = Rack::Mime::MIME_TYPES[File.extname(path)]
|
27
|
+
autoclose(file)
|
28
|
+
end
|
29
|
+
|
30
|
+
def uploaded_file_with_content(basename, content)
|
31
|
+
io = ActionController::UploadedStringIO.new(content)
|
32
|
+
io.original_path = basename
|
33
|
+
io.content_type = Rack::Mime::MIME_TYPES[File.extname(basename)]
|
34
|
+
io
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_file(basename)
|
38
|
+
path = test_path(basename)
|
39
|
+
file = open(path)
|
40
|
+
autoclose(file)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_path(basename)
|
44
|
+
"#{ROOT}/spec/data/#{basename}"
|
45
|
+
end
|
46
|
+
|
47
|
+
# For when it doesn't matter if it's small or large.
|
48
|
+
alias uploaded_file small_uploaded_file
|
49
|
+
|
50
|
+
def test_image_file(basename='test.jpg')
|
51
|
+
path = test_image_path(basename)
|
52
|
+
file = open(path)
|
53
|
+
autoclose(file)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_image_path(basename='test.jpg')
|
57
|
+
test_path(basename)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_video_file(basename='test.mov')
|
61
|
+
path = test_video_path(basename)
|
62
|
+
file = open(path)
|
63
|
+
autoclose(file)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_video_path(basename='test.mov')
|
67
|
+
test_path(basename)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_pdf_file(basename='test.pdf')
|
71
|
+
path = test_pdf_path(basename)
|
72
|
+
file = open(path)
|
73
|
+
autoclose(file)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_pdf_path(basename='test.pdf')
|
77
|
+
test_path(basename)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_empty_file
|
81
|
+
file = open(test_path('empty.txt'))
|
82
|
+
autoclose(file)
|
83
|
+
end
|
84
|
+
|
85
|
+
private # ---------------------------------------------------------
|
86
|
+
|
87
|
+
def init_test_upload_files
|
88
|
+
@files_to_close = []
|
89
|
+
end
|
90
|
+
|
91
|
+
def close_test_upload_files
|
92
|
+
@files_to_close.each(&:close)
|
93
|
+
end
|
94
|
+
|
95
|
+
def content_for_uploaded_file(test_file)
|
96
|
+
path = test_path("test#{File.extname(test_file)}")
|
97
|
+
File.read(path)
|
98
|
+
end
|
99
|
+
|
100
|
+
def unused_temp_path
|
101
|
+
i = 0
|
102
|
+
path = nil
|
103
|
+
begin
|
104
|
+
path = File.join(temporary_directory, "test-#{i}.jpg")
|
105
|
+
end while File.exist?(path)
|
106
|
+
path
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module TimeTravel
|
2
|
+
def self.included(mod)
|
3
|
+
mod.before{stop_time}
|
4
|
+
end
|
5
|
+
|
6
|
+
def stop_time
|
7
|
+
warp_to Time.now
|
8
|
+
end
|
9
|
+
|
10
|
+
def warp_to(time)
|
11
|
+
time = Time.parse(time) if time.is_a?(String)
|
12
|
+
Time.stubs(:now).returns(time)
|
13
|
+
end
|
14
|
+
|
15
|
+
def warp_ahead(duration)
|
16
|
+
new_now = Time.now + duration
|
17
|
+
Time.stubs(:now).returns(new_now)
|
18
|
+
new_now
|
19
|
+
end
|
20
|
+
end
|
Binary file
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Lifecycle hooks" do
|
4
|
+
use_model_class(:Thing,
|
5
|
+
:attachment_file_name => :string,
|
6
|
+
:value => :integer)
|
7
|
+
|
8
|
+
before do
|
9
|
+
@file = open("#{ROOT}/spec/integration/data/test.jpg")
|
10
|
+
Bulldog.default_url_template = "/attachments/:class/:id.:style.:extension"
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
@file.close
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should run before-validation hooks before validating the record" do
|
18
|
+
checks = []
|
19
|
+
Thing.validates_presence_of :value
|
20
|
+
Thing.has_attachment :attachment do
|
21
|
+
style :normal
|
22
|
+
process :before => :validation do
|
23
|
+
checks << record.errors.empty?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
thing = Thing.new(:attachment => @file)
|
27
|
+
checks.should == []
|
28
|
+
thing.valid?.should be_false
|
29
|
+
checks.should == [true]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should run after-validation hooks after validating the record" do
|
33
|
+
checks = []
|
34
|
+
Thing.validates_presence_of :value
|
35
|
+
Thing.has_attachment :attachment do
|
36
|
+
style :normal
|
37
|
+
process :after => :validation do
|
38
|
+
checks << record.errors.empty?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
thing = Thing.new(:attachment => @file)
|
42
|
+
checks.should == []
|
43
|
+
thing.valid?.should be_false
|
44
|
+
checks.should == [false]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should run before-save hooks before saving the record" do
|
48
|
+
checks = []
|
49
|
+
Thing.has_attachment :attachment do
|
50
|
+
style :normal
|
51
|
+
process :before => :save do
|
52
|
+
checks << record.new_record?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
thing = Thing.new(:attachment => @file)
|
56
|
+
checks.should == []
|
57
|
+
thing.save.should be_true
|
58
|
+
checks.should == [true]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should run after-save hooks after saving the record" do
|
62
|
+
checks = []
|
63
|
+
Thing.has_attachment :attachment do
|
64
|
+
style :normal
|
65
|
+
process :after => :save do
|
66
|
+
checks << record.new_record?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
thing = Thing.new(:attachment => @file)
|
70
|
+
checks.should == []
|
71
|
+
thing.save.should be_true
|
72
|
+
checks.should == [false]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should run before-create hooks before creating the record" do
|
76
|
+
checks = []
|
77
|
+
Thing.has_attachment :attachment do
|
78
|
+
style :normal
|
79
|
+
process :before => :create do
|
80
|
+
checks << record.new_record?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
thing = Thing.new(:attachment => @file)
|
84
|
+
checks.should == []
|
85
|
+
thing.save.should be_true
|
86
|
+
checks.should == [true]
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should run after-create hooks after creating the record" do
|
90
|
+
checks = []
|
91
|
+
Thing.has_attachment :attachment do
|
92
|
+
style :normal
|
93
|
+
process :after => :create do
|
94
|
+
checks << record.new_record?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
thing = Thing.new(:attachment => @file)
|
98
|
+
checks.should == []
|
99
|
+
thing.save.should be_true
|
100
|
+
checks.should == [false]
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should run before-update hooks before updating the record" do
|
104
|
+
checks = []
|
105
|
+
Thing.has_attachment :attachment do
|
106
|
+
style :normal
|
107
|
+
process :before => :update do
|
108
|
+
checks << Thing.count(:conditions => {:value => 2})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
Thing.create(:attachment => @file, :value => 1)
|
112
|
+
thing = Thing.first
|
113
|
+
checks.should == []
|
114
|
+
thing.update_attributes(:value => 2).should be_true
|
115
|
+
checks.should == [0]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should run after-update hooks after updating the record" do
|
119
|
+
checks = []
|
120
|
+
Thing.has_attachment :attachment do
|
121
|
+
style :normal
|
122
|
+
process :after => :update do
|
123
|
+
checks << Thing.count(:conditions => {:value => 2})
|
124
|
+
end
|
125
|
+
end
|
126
|
+
Thing.create(:attachment => @file, :value => 1)
|
127
|
+
thing = Thing.first
|
128
|
+
checks.should == []
|
129
|
+
thing.update_attributes(:value => 2).should be_true
|
130
|
+
checks.should == [1]
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not run create hooks when updating the record" do
|
134
|
+
checks = []
|
135
|
+
Thing.has_attachment :attachment do
|
136
|
+
style :normal
|
137
|
+
process :before => :update do
|
138
|
+
checks << [:fail]
|
139
|
+
end
|
140
|
+
|
141
|
+
process :after => :update do |thing|
|
142
|
+
checks << [:fail]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
Thing.create(:attachment => @file)
|
146
|
+
checks.should == []
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should not run update hooks when creating the record" do
|
150
|
+
checks = []
|
151
|
+
Thing.has_attachment :attachment do
|
152
|
+
style :normal
|
153
|
+
process :before => :create do
|
154
|
+
checks << [:fail]
|
155
|
+
end
|
156
|
+
|
157
|
+
process :after => :create do
|
158
|
+
checks << [:fail]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
thing = Thing.create(:attachment => @file, :value => 1)
|
162
|
+
checks = []
|
163
|
+
thing.update_attributes(:value => 2)
|
164
|
+
checks.should == []
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should run callbacks for the given attachment types if given" do
|
168
|
+
runs = 0
|
169
|
+
Thing.has_attachment :attachment do
|
170
|
+
style :normal
|
171
|
+
process(:types => :image, :on => :test_event){runs += 1}
|
172
|
+
end
|
173
|
+
thing = Thing.new(:attachment => @file)
|
174
|
+
thing.process_attachment(:attachment, :test_event)
|
175
|
+
runs.should == 1
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should not run callbacks if the attachment is of the wrong type" do
|
179
|
+
runs = 0
|
180
|
+
Thing.has_attachment :attachment do
|
181
|
+
style :normal
|
182
|
+
process(:types => :video, :on => :test_event){runs += 1}
|
183
|
+
end
|
184
|
+
thing = Thing.new(:attachment => @file)
|
185
|
+
thing.process_attachment(:attachment, :test_event)
|
186
|
+
runs.should == 0
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should allow specifying more than one type" do
|
190
|
+
runs = 0
|
191
|
+
Thing.has_attachment :attachment do
|
192
|
+
style :normal
|
193
|
+
process(:types => [:image, :video], :on => :test_event){runs += 1}
|
194
|
+
end
|
195
|
+
thing = Thing.new(:attachment => @file)
|
196
|
+
thing.process_attachment(:attachment, :test_event)
|
197
|
+
thing.attachment = uploaded_file_with_content('test.avi', "RIFF AVI ")
|
198
|
+
thing.process_attachment(:attachment, :test_event)
|
199
|
+
runs.should == 2
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should run multiple callbacks if given" do
|
203
|
+
checks = []
|
204
|
+
Thing.has_attachment :attachment do
|
205
|
+
style :normal
|
206
|
+
process(:on => :test_event){checks << 1}
|
207
|
+
process(:on => :test_event){checks << 2}
|
208
|
+
end
|
209
|
+
thing = Thing.new(:attachment => @file)
|
210
|
+
thing.process_attachment(:attachment, :test_event)
|
211
|
+
checks.should == [1, 2]
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Processing image attachments" do
|
4
|
+
use_model_class(:Thing,
|
5
|
+
:width => :integer,
|
6
|
+
:height => :integer)
|
7
|
+
|
8
|
+
def identify
|
9
|
+
Bulldog::Processor::ImageMagick.identify_command
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
tmp = temporary_directory
|
14
|
+
Thing.has_attachment :photo do
|
15
|
+
path "#{tmp}/:id.:style.png"
|
16
|
+
style :small, {:size => '10x10!'}
|
17
|
+
style :large, {:size => '1000x1000!'}
|
18
|
+
|
19
|
+
process :before => :save do
|
20
|
+
width, height = dimensions
|
21
|
+
record.width = width
|
22
|
+
record.height = height
|
23
|
+
end
|
24
|
+
|
25
|
+
process :on => :resize do
|
26
|
+
resize
|
27
|
+
end
|
28
|
+
end
|
29
|
+
@thing = Thing.new
|
30
|
+
@thing.stubs(:id).returns(5)
|
31
|
+
@file = small_uploaded_file(:size => "40x30")
|
32
|
+
end
|
33
|
+
|
34
|
+
def small_uploaded_file(options={})
|
35
|
+
tmp_path = "#{temporary_directory}/small_uploaded_file.tmp.png"
|
36
|
+
create_image(tmp_path, options)
|
37
|
+
content = File.read(tmp_path)
|
38
|
+
File.unlink(tmp_path)
|
39
|
+
|
40
|
+
io = ActionController::UploadedStringIO.new(content)
|
41
|
+
io.original_path = "tmp.png"
|
42
|
+
io.content_type = 'image/png'
|
43
|
+
io
|
44
|
+
end
|
45
|
+
|
46
|
+
after do
|
47
|
+
@file.close
|
48
|
+
end
|
49
|
+
|
50
|
+
def path(style)
|
51
|
+
"#{temporary_directory}/5.#{style}.png"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should run the after_save process after saving" do
|
55
|
+
@thing.update_attributes(:photo => @file)
|
56
|
+
@thing.width.should == 40
|
57
|
+
@thing.height.should == 30
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should process the attachment when the processor is run" do
|
61
|
+
File.exist?(path(:original)).should be_false
|
62
|
+
File.exist?(path(:small)).should be_false
|
63
|
+
File.exist?(path(:large)).should be_false
|
64
|
+
|
65
|
+
@thing.update_attributes(:photo => @file).should be_true
|
66
|
+
@thing.process_attachment(:photo, :resize)
|
67
|
+
|
68
|
+
`"#{identify}" -format "%w %h" "#{path(:original)}"`.chomp.should == '40 30'
|
69
|
+
`"#{identify}" -format "%w %h" "#{path(:small)}"`.chomp.should == '10 10'
|
70
|
+
`"#{identify}" -format "%w %h" "#{path(:large)}"`.chomp.should == '1000 1000'
|
71
|
+
end
|
72
|
+
end
|