popel-attachment_fu 1.0.4
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/README +200 -0
- data/VERSION.yml +4 -0
- data/lib/geometry.rb +93 -0
- data/lib/technoweenie/attachment_fu.rb +528 -0
- data/lib/technoweenie/attachment_fu/backends/db_file_backend.rb +39 -0
- data/lib/technoweenie/attachment_fu/backends/file_system_backend.rb +126 -0
- data/lib/technoweenie/attachment_fu/backends/s3_backend.rb +394 -0
- data/lib/technoweenie/attachment_fu/processors/core_image_processor.rb +59 -0
- data/lib/technoweenie/attachment_fu/processors/gd2_processor.rb +54 -0
- data/lib/technoweenie/attachment_fu/processors/image_science_processor.rb +61 -0
- data/lib/technoweenie/attachment_fu/processors/mini_magick_processor.rb +132 -0
- data/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb +57 -0
- data/test/backends/db_file_test.rb +16 -0
- data/test/backends/file_system_test.rb +143 -0
- data/test/backends/remote/s3_test.rb +119 -0
- data/test/base_attachment_tests.rb +77 -0
- data/test/basic_test.rb +70 -0
- data/test/database.yml +18 -0
- data/test/extra_attachment_test.rb +67 -0
- data/test/fixtures/attachment.rb +215 -0
- data/test/fixtures/files/fake/rails.png +0 -0
- data/test/fixtures/files/foo.txt +1 -0
- data/test/fixtures/files/rails.png +0 -0
- data/test/geometry_test.rb +108 -0
- data/test/processors/core_image_test.rb +37 -0
- data/test/processors/gd2_test.rb +31 -0
- data/test/processors/image_science_test.rb +31 -0
- data/test/processors/mini_magick_test.rb +103 -0
- data/test/processors/rmagick_test.rb +255 -0
- data/test/schema.rb +121 -0
- data/test/test_helper.rb +150 -0
- data/test/validation_test.rb +55 -0
- metadata +95 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'red_artisan/core_image/processor'
|
2
|
+
|
3
|
+
module Technoweenie # :nodoc:
|
4
|
+
module AttachmentFu # :nodoc:
|
5
|
+
module Processors
|
6
|
+
module CoreImageProcessor
|
7
|
+
def self.included(base)
|
8
|
+
base.send :extend, ClassMethods
|
9
|
+
base.alias_method_chain :process_attachment, :processing
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def with_image(file, &block)
|
14
|
+
block.call OSX::CIImage.from(file)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def process_attachment_with_processing
|
20
|
+
return unless process_attachment_without_processing
|
21
|
+
with_image do |img|
|
22
|
+
self.width = img.extent.size.width if respond_to?(:width)
|
23
|
+
self.height = img.extent.size.height if respond_to?(:height)
|
24
|
+
resize_image_or_thumbnail! img
|
25
|
+
callback_with_args :after_resize, img
|
26
|
+
end if image?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Performs the actual resizing operation for a thumbnail
|
30
|
+
def resize_image(img, size)
|
31
|
+
processor = ::RedArtisan::CoreImage::Processor.new(img)
|
32
|
+
size = size.first if size.is_a?(Array) && size.length == 1
|
33
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
34
|
+
if size.is_a?(Fixnum)
|
35
|
+
processor.fit(size)
|
36
|
+
else
|
37
|
+
processor.resize(size[0], size[1])
|
38
|
+
end
|
39
|
+
else
|
40
|
+
new_size = [img.extent.size.width, img.extent.size.height] / size.to_s
|
41
|
+
processor.resize(new_size[0], new_size[1])
|
42
|
+
end
|
43
|
+
|
44
|
+
processor.render do |result|
|
45
|
+
self.width = result.extent.size.width if respond_to?(:width)
|
46
|
+
self.height = result.extent.size.height if respond_to?(:height)
|
47
|
+
|
48
|
+
# Get a new temp_path for the image before saving
|
49
|
+
temp_paths.unshift Tempfile.new(random_tempfile_filename, Technoweenie::AttachmentFu.tempfile_path).path
|
50
|
+
result.save self.temp_path, OSX::NSJPEGFileType
|
51
|
+
self.size = File.size(self.temp_path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'gd2'
|
3
|
+
module Technoweenie # :nodoc:
|
4
|
+
module AttachmentFu # :nodoc:
|
5
|
+
module Processors
|
6
|
+
module Gd2Processor
|
7
|
+
def self.included(base)
|
8
|
+
base.send :extend, ClassMethods
|
9
|
+
base.alias_method_chain :process_attachment, :processing
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Yields a block containing a GD2 Image for the given binary data.
|
14
|
+
def with_image(file, &block)
|
15
|
+
im = GD2::Image.import(file)
|
16
|
+
block.call(im)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
def process_attachment_with_processing
|
22
|
+
return unless process_attachment_without_processing && image?
|
23
|
+
with_image do |img|
|
24
|
+
resize_image_or_thumbnail! img
|
25
|
+
self.width = img.width
|
26
|
+
self.height = img.height
|
27
|
+
callback_with_args :after_resize, img
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Performs the actual resizing operation for a thumbnail
|
32
|
+
def resize_image(img, size)
|
33
|
+
size = size.first if size.is_a?(Array) && size.length == 1
|
34
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
35
|
+
if size.is_a?(Fixnum)
|
36
|
+
# Borrowed from image science's #thumbnail method and adapted
|
37
|
+
# for this.
|
38
|
+
scale = size.to_f / (img.width > img.height ? img.width.to_f : img.height.to_f)
|
39
|
+
img.resize!((img.width * scale).round(1), (img.height * scale).round(1), false)
|
40
|
+
else
|
41
|
+
img.resize!(size.first, size.last, false)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
w, h = [img.width, img.height] / size.to_s
|
45
|
+
img.resize!(w, h, false)
|
46
|
+
end
|
47
|
+
temp_paths.unshift random_tempfile_filename
|
48
|
+
self.size = img.export(self.temp_path)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'image_science'
|
2
|
+
module Technoweenie # :nodoc:
|
3
|
+
module AttachmentFu # :nodoc:
|
4
|
+
module Processors
|
5
|
+
module ImageScienceProcessor
|
6
|
+
def self.included(base)
|
7
|
+
base.send :extend, ClassMethods
|
8
|
+
base.alias_method_chain :process_attachment, :processing
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Yields a block containing an Image Science image for the given binary data.
|
13
|
+
def with_image(file, &block)
|
14
|
+
::ImageScience.with_image file, &block
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def process_attachment_with_processing
|
20
|
+
return unless process_attachment_without_processing && image?
|
21
|
+
with_image do |img|
|
22
|
+
self.width = img.width if respond_to?(:width)
|
23
|
+
self.height = img.height if respond_to?(:height)
|
24
|
+
resize_image_or_thumbnail! img
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Performs the actual resizing operation for a thumbnail
|
29
|
+
def resize_image(img, size)
|
30
|
+
# create a dummy temp file to write to
|
31
|
+
# ImageScience doesn't handle all gifs properly, so it converts them to
|
32
|
+
# pngs for thumbnails. It has something to do with trying to save gifs
|
33
|
+
# with a larger palette than 256 colors, which is all the gif format
|
34
|
+
# supports.
|
35
|
+
filename.sub! /gif$/, 'png'
|
36
|
+
content_type.sub!(/gif$/, 'png')
|
37
|
+
temp_paths.unshift write_to_temp_file(filename)
|
38
|
+
grab_dimensions = lambda do |img|
|
39
|
+
self.width = img.width if respond_to?(:width)
|
40
|
+
self.height = img.height if respond_to?(:height)
|
41
|
+
img.save self.temp_path
|
42
|
+
self.size = File.size(self.temp_path)
|
43
|
+
callback_with_args :after_resize, img
|
44
|
+
end
|
45
|
+
|
46
|
+
size = size.first if size.is_a?(Array) && size.length == 1
|
47
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
48
|
+
if size.is_a?(Fixnum)
|
49
|
+
img.thumbnail(size, &grab_dimensions)
|
50
|
+
else
|
51
|
+
img.resize(size[0], size[1], &grab_dimensions)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
new_size = [img.width, img.height] / size.to_s
|
55
|
+
img.resize(new_size[0], new_size[1], &grab_dimensions)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
module Technoweenie # :nodoc:
|
3
|
+
module AttachmentFu # :nodoc:
|
4
|
+
module Processors
|
5
|
+
module MiniMagickProcessor
|
6
|
+
def self.included(base)
|
7
|
+
base.send :extend, ClassMethods
|
8
|
+
base.alias_method_chain :process_attachment, :processing
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Yields a block containing an MiniMagick Image for the given binary data.
|
13
|
+
def with_image(file, &block)
|
14
|
+
begin
|
15
|
+
binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.from_file(file) unless !Object.const_defined?(:MiniMagick)
|
16
|
+
rescue
|
17
|
+
# Log the failure to load the image.
|
18
|
+
logger.debug("Exception working with image: #{$!}")
|
19
|
+
binary_data = nil
|
20
|
+
end
|
21
|
+
block.call binary_data if block && binary_data
|
22
|
+
ensure
|
23
|
+
!binary_data.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def process_attachment_with_processing
|
29
|
+
return unless process_attachment_without_processing
|
30
|
+
with_image do |img|
|
31
|
+
resize_image_or_thumbnail! img
|
32
|
+
self.width = img[:width] if respond_to?(:width)
|
33
|
+
self.height = img[:height] if respond_to?(:height)
|
34
|
+
callback_with_args :after_resize, img
|
35
|
+
end if image?
|
36
|
+
end
|
37
|
+
|
38
|
+
# Performs the actual resizing operation for a thumbnail
|
39
|
+
def resize_image(img, size)
|
40
|
+
size = size.first if size.is_a?(Array) && size.length == 1
|
41
|
+
img.combine_options do |commands|
|
42
|
+
commands.strip unless attachment_options[:keep_profile]
|
43
|
+
|
44
|
+
# gif are not handled correct, this is a hack, but it seems to work.
|
45
|
+
if img.output =~ / GIF /
|
46
|
+
img.format("png")
|
47
|
+
end
|
48
|
+
|
49
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
50
|
+
if size.is_a?(Fixnum)
|
51
|
+
size = [size, size]
|
52
|
+
commands.resize(size.join('x'))
|
53
|
+
else
|
54
|
+
commands.resize(size.join('x') + '!')
|
55
|
+
end
|
56
|
+
# extend to thumbnail size
|
57
|
+
elsif size.is_a?(String) and size =~ /e$/
|
58
|
+
size = size.gsub(/e/, '')
|
59
|
+
commands.resize(size.to_s + '>')
|
60
|
+
commands.background('#ffffff')
|
61
|
+
commands.gravity('center')
|
62
|
+
commands.extent(size)
|
63
|
+
# crop thumbnail, the smart way
|
64
|
+
elsif size.is_a?(String) and size =~ /c$/
|
65
|
+
size = size.gsub(/c/, '')
|
66
|
+
|
67
|
+
# calculate sizes and aspect ratio
|
68
|
+
thumb_width, thumb_height = size.split("x")
|
69
|
+
thumb_width = thumb_width.to_f
|
70
|
+
thumb_height = thumb_height.to_f
|
71
|
+
|
72
|
+
thumb_aspect = thumb_width.to_f / thumb_height.to_f
|
73
|
+
image_width, image_height = img[:width].to_f, img[:height].to_f
|
74
|
+
image_aspect = image_width / image_height
|
75
|
+
|
76
|
+
# only crop if image is not smaller in both dimensions
|
77
|
+
unless image_width < thumb_width and image_height < thumb_height
|
78
|
+
command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
|
79
|
+
|
80
|
+
# crop image
|
81
|
+
commands.extract(command)
|
82
|
+
end
|
83
|
+
|
84
|
+
# don not resize if image is not as height or width then thumbnail
|
85
|
+
if image_width < thumb_width or image_height < thumb_height
|
86
|
+
commands.background('#ffffff')
|
87
|
+
commands.gravity('center')
|
88
|
+
commands.extent(size)
|
89
|
+
# resize image
|
90
|
+
else
|
91
|
+
commands.resize("#{size.to_s}")
|
92
|
+
end
|
93
|
+
# crop end
|
94
|
+
else
|
95
|
+
commands.resize(size.to_s)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
temp_paths.unshift img
|
99
|
+
end
|
100
|
+
|
101
|
+
def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
|
102
|
+
# only crop if image is not smaller in both dimensions
|
103
|
+
|
104
|
+
# special cases, image smaller in one dimension then thumbsize
|
105
|
+
if image_width < thumb_width
|
106
|
+
offset = (image_height / 2) - (thumb_height / 2)
|
107
|
+
command = "#{image_width}x#{thumb_height}+0+#{offset}"
|
108
|
+
elsif image_height < thumb_height
|
109
|
+
offset = (image_width / 2) - (thumb_width / 2)
|
110
|
+
command = "#{thumb_width}x#{image_height}+#{offset}+0"
|
111
|
+
|
112
|
+
# normal thumbnail generation
|
113
|
+
# calculate height and offset y, width is fixed
|
114
|
+
elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
|
115
|
+
height = image_width / thumb_aspect
|
116
|
+
offset = (image_height / 2) - (height / 2)
|
117
|
+
command = "#{image_width}x#{height}+0+#{offset}"
|
118
|
+
# calculate width and offset x, height is fixed
|
119
|
+
else
|
120
|
+
width = image_height * thumb_aspect
|
121
|
+
offset = (image_width / 2) - (width / 2)
|
122
|
+
command = "#{width}x#{image_height}+#{offset}+0"
|
123
|
+
end
|
124
|
+
# crop image
|
125
|
+
command
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'RMagick'
|
2
|
+
module Technoweenie # :nodoc:
|
3
|
+
module AttachmentFu # :nodoc:
|
4
|
+
module Processors
|
5
|
+
module RmagickProcessor
|
6
|
+
def self.included(base)
|
7
|
+
base.send :extend, ClassMethods
|
8
|
+
base.alias_method_chain :process_attachment, :processing
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Yields a block containing an RMagick Image for the given binary data.
|
13
|
+
def with_image(file, &block)
|
14
|
+
begin
|
15
|
+
binary_data = file.is_a?(Magick::Image) ? file : Magick::Image.read(file).first unless !Object.const_defined?(:Magick)
|
16
|
+
rescue
|
17
|
+
# Log the failure to load the image. This should match ::Magick::ImageMagickError
|
18
|
+
# but that would cause acts_as_attachment to require rmagick.
|
19
|
+
logger.debug("Exception working with image: #{$!}")
|
20
|
+
binary_data = nil
|
21
|
+
end
|
22
|
+
block.call binary_data if block && binary_data
|
23
|
+
ensure
|
24
|
+
!binary_data.nil?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def process_attachment_with_processing
|
30
|
+
return unless process_attachment_without_processing
|
31
|
+
with_image do |img|
|
32
|
+
resize_image_or_thumbnail! img
|
33
|
+
self.width = img.columns if respond_to?(:width)
|
34
|
+
self.height = img.rows if respond_to?(:height)
|
35
|
+
callback_with_args :after_resize, img
|
36
|
+
end if image?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Performs the actual resizing operation for a thumbnail
|
40
|
+
def resize_image(img, size)
|
41
|
+
size = size.first if size.is_a?(Array) && size.length == 1 && !size.first.is_a?(Fixnum)
|
42
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
43
|
+
size = [size, size] if size.is_a?(Fixnum)
|
44
|
+
img.thumbnail!(*size)
|
45
|
+
elsif size.is_a?(String) && size =~ /^c.*$/ # Image cropping - example geometry string: c75x75
|
46
|
+
dimensions = size[1..size.size].split("x")
|
47
|
+
img.crop_resized!(dimensions[0].to_i, dimensions[1].to_i)
|
48
|
+
else
|
49
|
+
img.change_geometry(size.to_s) { |cols, rows, image| image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows) }
|
50
|
+
end
|
51
|
+
img.strip! unless attachment_options[:keep_profile]
|
52
|
+
temp_paths.unshift write_to_temp_file(img.to_blob)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
class DbFileTest < Test::Unit::TestCase
|
4
|
+
include BaseAttachmentTests
|
5
|
+
attachment_model Attachment
|
6
|
+
|
7
|
+
def test_should_call_after_attachment_saved(klass = Attachment)
|
8
|
+
attachment_model.saves = 0
|
9
|
+
assert_created do
|
10
|
+
upload_file :filename => '/files/rails.png'
|
11
|
+
end
|
12
|
+
assert_equal 1, attachment_model.saves
|
13
|
+
end
|
14
|
+
|
15
|
+
test_against_subclass :test_should_call_after_attachment_saved, Attachment
|
16
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
require 'digest/sha2'
|
3
|
+
|
4
|
+
class FileSystemTest < Test::Unit::TestCase
|
5
|
+
include BaseAttachmentTests
|
6
|
+
attachment_model FileAttachment
|
7
|
+
|
8
|
+
def test_filesystem_size_for_file_attachment(klass = FileAttachment)
|
9
|
+
attachment_model klass
|
10
|
+
assert_created 1 do
|
11
|
+
attachment = upload_file :filename => '/files/rails.png'
|
12
|
+
assert_equal attachment.size, File.open(attachment.full_filename).stat.size
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test_against_subclass :test_filesystem_size_for_file_attachment, FileAttachment
|
17
|
+
|
18
|
+
def test_should_not_overwrite_file_attachment(klass = FileAttachment)
|
19
|
+
attachment_model klass
|
20
|
+
assert_created 2 do
|
21
|
+
real = upload_file :filename => '/files/rails.png'
|
22
|
+
assert_valid real
|
23
|
+
assert !real.new_record?, real.errors.full_messages.join("\n")
|
24
|
+
assert !real.size.zero?
|
25
|
+
|
26
|
+
fake = upload_file :filename => '/files/fake/rails.png'
|
27
|
+
assert_valid fake
|
28
|
+
assert !fake.size.zero?
|
29
|
+
|
30
|
+
assert_not_equal File.open(real.full_filename).stat.size, File.open(fake.full_filename).stat.size
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
test_against_subclass :test_should_not_overwrite_file_attachment, FileAttachment
|
35
|
+
|
36
|
+
def test_should_store_file_attachment_in_filesystem(klass = FileAttachment)
|
37
|
+
attachment_model klass
|
38
|
+
attachment = nil
|
39
|
+
assert_created do
|
40
|
+
attachment = upload_file :filename => '/files/rails.png'
|
41
|
+
assert_valid attachment
|
42
|
+
assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
|
43
|
+
end
|
44
|
+
attachment
|
45
|
+
end
|
46
|
+
|
47
|
+
test_against_subclass :test_should_store_file_attachment_in_filesystem, FileAttachment
|
48
|
+
|
49
|
+
def test_should_delete_old_file_when_updating(klass = FileAttachment)
|
50
|
+
attachment_model klass
|
51
|
+
attachment = upload_file :filename => '/files/rails.png'
|
52
|
+
old_filename = attachment.full_filename
|
53
|
+
assert_not_created do
|
54
|
+
use_temp_file 'files/rails.png' do |file|
|
55
|
+
attachment.filename = 'rails2.png'
|
56
|
+
attachment.temp_paths.unshift File.join(fixture_path, file)
|
57
|
+
attachment.save!
|
58
|
+
assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
|
59
|
+
assert !File.exists?(old_filename), "#{old_filename} still exists"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
test_against_subclass :test_should_delete_old_file_when_updating, FileAttachment
|
65
|
+
|
66
|
+
def test_should_delete_old_file_when_renaming(klass = FileAttachment)
|
67
|
+
attachment_model klass
|
68
|
+
attachment = upload_file :filename => '/files/rails.png'
|
69
|
+
old_filename = attachment.full_filename
|
70
|
+
assert_not_created do
|
71
|
+
attachment.filename = 'rails2.png'
|
72
|
+
attachment.save
|
73
|
+
assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
|
74
|
+
assert !File.exists?(old_filename), "#{old_filename} still exists"
|
75
|
+
assert !attachment.reload.size.zero?
|
76
|
+
assert_equal 'rails2.png', attachment.filename
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
test_against_subclass :test_should_delete_old_file_when_renaming, FileAttachment
|
81
|
+
|
82
|
+
def test_path_partitioning_works_on_integer_id(klass = FileAttachment)
|
83
|
+
attachment_model klass
|
84
|
+
|
85
|
+
# Create a random attachment object, doesn't matter what.
|
86
|
+
attachment = upload_file :filename => '/files/rails.png'
|
87
|
+
old_id = attachment.id
|
88
|
+
attachment.id = 1
|
89
|
+
|
90
|
+
begin
|
91
|
+
assert_equal ["0000", "0001", "bar.txt"], attachment.send(:partitioned_path, "bar.txt")
|
92
|
+
ensure
|
93
|
+
attachment.id = old_id
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
test_against_subclass :test_path_partitioning_works_on_integer_id, FileAttachment
|
98
|
+
|
99
|
+
def test_path_partitioning_with_string_id_works_by_generating_hash(klass = FileAttachmentWithStringId)
|
100
|
+
attachment_model klass
|
101
|
+
|
102
|
+
# Create a random attachment object, doesn't matter what.
|
103
|
+
attachment = upload_file :filename => '/files/rails.png'
|
104
|
+
old_id = attachment.id
|
105
|
+
attachment.id = "hello world some long string"
|
106
|
+
hash = Digest::SHA512.hexdigest("hello world some long string")
|
107
|
+
|
108
|
+
begin
|
109
|
+
assert_equal [
|
110
|
+
hash[0..31],
|
111
|
+
hash[32..63],
|
112
|
+
hash[64..95],
|
113
|
+
hash[96..127],
|
114
|
+
"bar.txt"
|
115
|
+
], attachment.send(:partitioned_path, "bar.txt")
|
116
|
+
ensure
|
117
|
+
attachment.id = old_id
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
test_against_subclass :test_path_partitioning_with_string_id_works_by_generating_hash, FileAttachmentWithStringId
|
122
|
+
|
123
|
+
def test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid(klass = FileAttachmentWithUuid)
|
124
|
+
attachment_model klass
|
125
|
+
|
126
|
+
# Create a random attachment object, doesn't matter what.
|
127
|
+
attachment = upload_file :filename => '/files/rails.png'
|
128
|
+
old_id = attachment.id
|
129
|
+
attachment.id = "0c0743b698483569dc65909a8cdb3bf9"
|
130
|
+
|
131
|
+
begin
|
132
|
+
assert_equal [
|
133
|
+
"0c0743b698483569",
|
134
|
+
"dc65909a8cdb3bf9",
|
135
|
+
"bar.txt"
|
136
|
+
], attachment.send(:partitioned_path, "bar.txt")
|
137
|
+
ensure
|
138
|
+
attachment.id = old_id
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
test_against_subclass :test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid, FileAttachmentWithUuid
|
143
|
+
end
|