file_column 0.3.2
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/CHANGELOG +69 -0
- data/Gemfile +10 -0
- data/README +54 -0
- data/Rakefile +50 -0
- data/TODO +6 -0
- data/VERSION +1 -0
- data/init.rb +12 -0
- data/lib/file_column.rb +721 -0
- data/lib/file_column_helper.rb +150 -0
- data/lib/file_compat.rb +28 -0
- data/lib/magick_file_column.rb +265 -0
- data/lib/rails_file_column.rb +19 -0
- data/lib/test_case.rb +124 -0
- data/lib/validations.rb +112 -0
- data/test/abstract_unit.rb +63 -0
- data/test/connection.rb +17 -0
- data/test/file_column_helper_test.rb +97 -0
- data/test/file_column_test.rb +650 -0
- data/test/fixtures/entry.rb +32 -0
- data/test/fixtures/invalid-image.jpg +1 -0
- data/test/fixtures/kerb.jpg +0 -0
- data/test/fixtures/mysql.sql +25 -0
- data/test/fixtures/schema.rb +10 -0
- data/test/fixtures/skanthak.png +0 -0
- data/test/magick_test.rb +380 -0
- data/test/magick_view_only_test.rb +21 -0
- metadata +86 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
class Entry < ActiveRecord::Base
|
2
|
+
attr_accessor :validation_should_fail
|
3
|
+
|
4
|
+
def validate
|
5
|
+
errors.add("image","some stupid error") if @validation_should_fail
|
6
|
+
end
|
7
|
+
|
8
|
+
def after_assign
|
9
|
+
@after_assign_called = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_assign_called?
|
13
|
+
@after_assign_called
|
14
|
+
end
|
15
|
+
|
16
|
+
def after_save
|
17
|
+
@after_save_called = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_save_called?
|
21
|
+
@after_save_called
|
22
|
+
end
|
23
|
+
|
24
|
+
def my_store_dir
|
25
|
+
# not really dynamic but at least it could be...
|
26
|
+
"my_store_dir"
|
27
|
+
end
|
28
|
+
|
29
|
+
def load_image_with_rmagick(path)
|
30
|
+
Magick::Image::read(path).first
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
this is certainly not a JPEG image
|
Binary file
|
@@ -0,0 +1,25 @@
|
|
1
|
+
-- MySQL dump 9.11
|
2
|
+
--
|
3
|
+
-- Host: localhost Database: file_column_test
|
4
|
+
-- ------------------------------------------------------
|
5
|
+
-- Server version 4.0.24
|
6
|
+
|
7
|
+
--
|
8
|
+
-- Table structure for table `entries`
|
9
|
+
--
|
10
|
+
|
11
|
+
DROP TABLE IF EXISTS entries;
|
12
|
+
CREATE TABLE entries (
|
13
|
+
id int(11) NOT NULL auto_increment,
|
14
|
+
image varchar(200) default NULL,
|
15
|
+
file varchar(200) NOT NULL,
|
16
|
+
PRIMARY KEY (id)
|
17
|
+
) TYPE=MyISAM;
|
18
|
+
|
19
|
+
DROP TABLE IF EXISTS movies;
|
20
|
+
CREATE TABLE movies (
|
21
|
+
id int(11) NOT NULL auto_increment,
|
22
|
+
movie varchar(200) default NULL,
|
23
|
+
PRIMARY KEY (id)
|
24
|
+
) TYPE=MyISAM;
|
25
|
+
|
Binary file
|
data/test/magick_test.rb
ADDED
@@ -0,0 +1,380 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
require 'RMagick'
|
3
|
+
require File.dirname(__FILE__) + '/fixtures/entry'
|
4
|
+
|
5
|
+
|
6
|
+
class AbstractRMagickTest < Test::Unit::TestCase
|
7
|
+
def teardown
|
8
|
+
FileUtils.rm_rf File.dirname(__FILE__)+"/public/entry/"
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_truth
|
12
|
+
assert true
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def read_image(path)
|
18
|
+
Magick::Image::read(path).first
|
19
|
+
end
|
20
|
+
|
21
|
+
def assert_max_image_size(img, s)
|
22
|
+
assert img.columns <= s, "img has #{img.columns} columns, expected: #{s}"
|
23
|
+
assert img.rows <= s, "img has #{img.rows} rows, expected: #{s}"
|
24
|
+
assert_equal s, [img.columns, img.rows].max
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class RMagickSimpleTest < AbstractRMagickTest
|
29
|
+
def setup
|
30
|
+
Entry.file_column :image, :magick => { :geometry => "100x100" }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_simple_resize_without_save
|
34
|
+
e = Entry.new
|
35
|
+
e.image = upload(f("kerb.jpg"))
|
36
|
+
|
37
|
+
img = read_image(e.image)
|
38
|
+
assert_max_image_size img, 100
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_simple_resize_with_save
|
42
|
+
e = Entry.new
|
43
|
+
e.image = upload(f("kerb.jpg"))
|
44
|
+
assert e.save
|
45
|
+
e.reload
|
46
|
+
|
47
|
+
img = read_image(e.image)
|
48
|
+
assert_max_image_size img, 100
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_resize_on_saved_image
|
52
|
+
Entry.file_column :image, :magick => { :geometry => "100x100" }
|
53
|
+
|
54
|
+
e = Entry.new
|
55
|
+
e.image = upload(f("skanthak.png"))
|
56
|
+
assert e.save
|
57
|
+
e.reload
|
58
|
+
old_path = e.image
|
59
|
+
|
60
|
+
e.image = upload(f("kerb.jpg"))
|
61
|
+
assert e.save
|
62
|
+
assert "kerb.jpg", File.basename(e.image)
|
63
|
+
assert !File.exists?(old_path), "old image '#{old_path}' still exists"
|
64
|
+
|
65
|
+
img = read_image(e.image)
|
66
|
+
assert_max_image_size img, 100
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_invalid_image
|
70
|
+
e = Entry.new
|
71
|
+
assert_nothing_raised { e.image = upload(f("invalid-image.jpg")) }
|
72
|
+
assert !e.valid?
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_serializable
|
76
|
+
e = Entry.new
|
77
|
+
e.image = upload(f("skanthak.png"))
|
78
|
+
assert_nothing_raised {
|
79
|
+
flash = Marshal.dump(e)
|
80
|
+
e = Marshal.load(flash)
|
81
|
+
}
|
82
|
+
assert File.exists?(e.image)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_imagemagick_still_usable
|
86
|
+
e = Entry.new
|
87
|
+
assert_nothing_raised {
|
88
|
+
img = e.load_image_with_rmagick(file_path("skanthak.png"))
|
89
|
+
assert img.kind_of?(Magick::Image)
|
90
|
+
}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class RMagickRequiresImageTest < AbstractRMagickTest
|
95
|
+
def setup
|
96
|
+
Entry.file_column :image, :magick => {
|
97
|
+
:size => "100x100>",
|
98
|
+
:image_required => false,
|
99
|
+
:versions => {
|
100
|
+
:thumb => "80x80>",
|
101
|
+
:large => {:size => "200x200>", :lazy => true}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_image_required_with_image
|
107
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
108
|
+
assert_max_image_size read_image(e.image), 100
|
109
|
+
assert e.valid?
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_image_required_with_invalid_image
|
113
|
+
e = Entry.new(:image => upload(f("invalid-image.jpg")))
|
114
|
+
assert e.valid?, "did not ignore invalid image"
|
115
|
+
assert FileUtils.identical?(e.image, f("invalid-image.jpg")), "uploaded file has not been left alone"
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_versions_with_invalid_image
|
119
|
+
e = Entry.new(:image => upload(f("invalid-image.jpg")))
|
120
|
+
assert e.valid?
|
121
|
+
|
122
|
+
image_state = e.send(:image_state)
|
123
|
+
assert_nil image_state.create_magick_version_if_needed(:thumb)
|
124
|
+
assert_nil image_state.create_magick_version_if_needed(:large)
|
125
|
+
assert_nil image_state.create_magick_version_if_needed("300x300>")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class RMagickCustomAttributesTest < AbstractRMagickTest
|
130
|
+
def assert_image_property(img, property, value, text = nil)
|
131
|
+
assert File.exists?(img), "the image does not exist"
|
132
|
+
assert_equal value, read_image(img).send(property), text
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_simple_attributes
|
136
|
+
Entry.file_column :image, :magick => { :attributes => { :quality => 20 } }
|
137
|
+
e = Entry.new("image" => upload(f("kerb.jpg")))
|
138
|
+
assert_image_property e.image, :quality, 20, "the quality was not set"
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_version_attributes
|
142
|
+
Entry.file_column :image, :magick => {
|
143
|
+
:versions => {
|
144
|
+
:thumb => { :attributes => { :quality => 20 } }
|
145
|
+
}
|
146
|
+
}
|
147
|
+
e = Entry.new("image" => upload(f("kerb.jpg")))
|
148
|
+
assert_image_property e.image("thumb"), :quality, 20, "the quality was not set"
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_lazy_attributes
|
152
|
+
Entry.file_column :image, :magick => {
|
153
|
+
:versions => {
|
154
|
+
:thumb => { :attributes => { :quality => 20 }, :lazy => true }
|
155
|
+
}
|
156
|
+
}
|
157
|
+
e = Entry.new("image" => upload(f("kerb.jpg")))
|
158
|
+
e.send(:image_state).create_magick_version_if_needed(:thumb)
|
159
|
+
assert_image_property e.image("thumb"), :quality, 20, "the quality was not set"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class RMagickVersionsTest < AbstractRMagickTest
|
164
|
+
def setup
|
165
|
+
Entry.file_column :image, :magick => {:geometry => "200x200",
|
166
|
+
:versions => {
|
167
|
+
:thumb => "50x50",
|
168
|
+
:medium => {:geometry => "100x100", :name => "100_100"},
|
169
|
+
:large => {:geometry => "150x150", :lazy => true}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
def test_should_create_thumb
|
176
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
177
|
+
|
178
|
+
assert File.exists?(e.image("thumb")), "thumb-nail not created"
|
179
|
+
|
180
|
+
assert_max_image_size read_image(e.image("thumb")), 50
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_version_name_can_be_different_from_key
|
184
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
185
|
+
|
186
|
+
assert File.exists?(e.image("100_100"))
|
187
|
+
assert !File.exists?(e.image("medium"))
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_should_not_create_lazy_versions
|
191
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
192
|
+
assert !File.exists?(e.image("large")), "lazy versions should not be created unless needed"
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_should_create_lazy_version_on_demand
|
196
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
197
|
+
|
198
|
+
e.send(:image_state).create_magick_version_if_needed(:large)
|
199
|
+
|
200
|
+
assert File.exists?(e.image("large")), "lazy version should be created on demand"
|
201
|
+
|
202
|
+
assert_max_image_size read_image(e.image("large")), 150
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_generated_name_should_not_change
|
206
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
207
|
+
|
208
|
+
name1 = e.send(:image_state).create_magick_version_if_needed("50x50")
|
209
|
+
name2 = e.send(:image_state).create_magick_version_if_needed("50x50")
|
210
|
+
name3 = e.send(:image_state).create_magick_version_if_needed(:geometry => "50x50")
|
211
|
+
assert_equal name1, name2, "hash value has changed"
|
212
|
+
assert_equal name1, name3, "hash value has changed"
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_should_create_version_with_string
|
216
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
217
|
+
|
218
|
+
name = e.send(:image_state).create_magick_version_if_needed("32x32")
|
219
|
+
|
220
|
+
assert File.exists?(e.image(name))
|
221
|
+
|
222
|
+
assert_max_image_size read_image(e.image(name)), 32
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_should_create_safe_auto_id
|
226
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
227
|
+
|
228
|
+
name = e.send(:image_state).create_magick_version_if_needed("32x32")
|
229
|
+
|
230
|
+
assert_match /^[a-zA-Z0-9]+$/, name
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
class RMagickCroppingTest < AbstractRMagickTest
|
235
|
+
def setup
|
236
|
+
Entry.file_column :image, :magick => {:geometry => "200x200",
|
237
|
+
:versions => {
|
238
|
+
:thumb => {:crop => "1:1", :geometry => "50x50"}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_should_crop_image_on_upload
|
244
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
245
|
+
|
246
|
+
img = read_image(e.image("thumb"))
|
247
|
+
|
248
|
+
assert_equal 50, img.rows
|
249
|
+
assert_equal 50, img.columns
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
class UrlForImageColumnTest < AbstractRMagickTest
|
255
|
+
include FileColumnHelper
|
256
|
+
|
257
|
+
def setup
|
258
|
+
Entry.file_column :image, :magick => {
|
259
|
+
:versions => {:thumb => "50x50"}
|
260
|
+
}
|
261
|
+
@request = RequestMock.new
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_should_use_version_on_symbol_option
|
265
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
266
|
+
|
267
|
+
url = url_for_image_column(e, "image", :thumb)
|
268
|
+
assert_match %r{^/entry/image/tmp/.+/thumb/skanthak.png$}, url
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_should_use_string_as_size
|
272
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
273
|
+
|
274
|
+
url = url_for_image_column(e, "image", "50x50")
|
275
|
+
|
276
|
+
assert_match %r{^/entry/image/tmp/.+/.+/skanthak.png$}, url
|
277
|
+
|
278
|
+
url =~ /\/([^\/]+)\/skanthak.png$/
|
279
|
+
dirname = $1
|
280
|
+
|
281
|
+
assert_max_image_size read_image(e.image(dirname)), 50
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_should_accept_version_hash
|
285
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
286
|
+
|
287
|
+
url = url_for_image_column(e, "image", :size => "50x50", :crop => "1:1", :name => "small")
|
288
|
+
|
289
|
+
assert_match %r{^/entry/image/tmp/.+/small/skanthak.png$}, url
|
290
|
+
|
291
|
+
img = read_image(e.image("small"))
|
292
|
+
assert_equal 50, img.rows
|
293
|
+
assert_equal 50, img.columns
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
class RMagickPermissionsTest < AbstractRMagickTest
|
298
|
+
def setup
|
299
|
+
Entry.file_column :image, :magick => {:geometry => "200x200",
|
300
|
+
:versions => {
|
301
|
+
:thumb => {:crop => "1:1", :geometry => "50x50"}
|
302
|
+
}
|
303
|
+
}, :permissions => 0616
|
304
|
+
end
|
305
|
+
|
306
|
+
def check_permissions(e)
|
307
|
+
assert_equal 0616, (File.stat(e.image).mode & 0777)
|
308
|
+
assert_equal 0616, (File.stat(e.image("thumb")).mode & 0777)
|
309
|
+
end
|
310
|
+
|
311
|
+
def test_permissions_with_rmagick
|
312
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
313
|
+
|
314
|
+
check_permissions e
|
315
|
+
|
316
|
+
assert e.save
|
317
|
+
|
318
|
+
check_permissions e
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
class Entry
|
323
|
+
def transform_grey(img)
|
324
|
+
img.quantize(256, Magick::GRAYColorspace)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
class RMagickTransformationTest < AbstractRMagickTest
|
329
|
+
def assert_transformed(image)
|
330
|
+
assert File.exists?(image), "the image does not exist"
|
331
|
+
assert 256 > read_image(image).number_colors, "the number of colors was not changed"
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_simple_transformation
|
335
|
+
Entry.file_column :image, :magick => { :transformation => Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) } }
|
336
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
337
|
+
assert_transformed(e.image)
|
338
|
+
end
|
339
|
+
|
340
|
+
def test_simple_version_transformation
|
341
|
+
Entry.file_column :image, :magick => {
|
342
|
+
:versions => { :thumb => Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) } }
|
343
|
+
}
|
344
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
345
|
+
assert_transformed(e.image("thumb"))
|
346
|
+
end
|
347
|
+
|
348
|
+
def test_complex_version_transformation
|
349
|
+
Entry.file_column :image, :magick => {
|
350
|
+
:versions => {
|
351
|
+
:thumb => { :transformation => Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) } }
|
352
|
+
}
|
353
|
+
}
|
354
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
355
|
+
assert_transformed(e.image("thumb"))
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_lazy_transformation
|
359
|
+
Entry.file_column :image, :magick => {
|
360
|
+
:versions => {
|
361
|
+
:thumb => { :transformation => Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) }, :lazy => true }
|
362
|
+
}
|
363
|
+
}
|
364
|
+
e = Entry.new("image" => upload(f("skanthak.png")))
|
365
|
+
e.send(:image_state).create_magick_version_if_needed(:thumb)
|
366
|
+
assert_transformed(e.image("thumb"))
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_simple_callback_transformation
|
370
|
+
Entry.file_column :image, :magick => :transform_grey
|
371
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
372
|
+
assert_transformed(e.image)
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_complex_callback_transformation
|
376
|
+
Entry.file_column :image, :magick => { :transformation => :transform_grey }
|
377
|
+
e = Entry.new(:image => upload(f("skanthak.png")))
|
378
|
+
assert_transformed(e.image)
|
379
|
+
end
|
380
|
+
end
|