attachmerb_fu 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README +166 -0
- data/Rakefile +35 -0
- data/TODO +5 -0
- data/lib/amazon_s3.yml.tpl +14 -0
- data/lib/attachment_fu.rb +431 -0
- data/lib/attachmerb_fu.rb +446 -0
- data/lib/attachmerb_fu/backends/db_file_backend.rb +37 -0
- data/lib/attachmerb_fu/backends/file_system_backend.rb +95 -0
- data/lib/attachmerb_fu/backends/s3_backend.rb +307 -0
- data/lib/attachmerb_fu/merbtasks.rb +6 -0
- data/lib/attachmerb_fu/processors/image_science_processor.rb +60 -0
- data/lib/attachmerb_fu/processors/mini_magick_processor.rb +54 -0
- data/lib/attachmerb_fu/processors/rmagick_processor.rb +51 -0
- data/lib/geometry.rb +93 -0
- data/lib/tempfile_ext.rb +9 -0
- data/lib/test/amazon_s3.yml +6 -0
- data/lib/test/backends/db_file_test.rb +16 -0
- data/lib/test/backends/file_system_test.rb +80 -0
- data/lib/test/backends/remote/s3_test.rb +103 -0
- data/lib/test/base_attachment_tests.rb +57 -0
- data/lib/test/basic_test.rb +64 -0
- data/lib/test/database.yml +18 -0
- data/lib/test/extra_attachment_test.rb +57 -0
- data/lib/test/fixtures/attachment.rb +127 -0
- data/lib/test/fixtures/files/fake/rails.png +0 -0
- data/lib/test/fixtures/files/foo.txt +1 -0
- data/lib/test/fixtures/files/rails.png +0 -0
- data/lib/test/geometry_test.rb +101 -0
- data/lib/test/processors/image_science_test.rb +31 -0
- data/lib/test/processors/mini_magick_test.rb +31 -0
- data/lib/test/processors/rmagick_test.rb +241 -0
- data/lib/test/schema.rb +86 -0
- data/lib/test/test_helper.rb +142 -0
- data/lib/test/validation_test.rb +55 -0
- metadata +107 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
module AttachmerbFu # :nodoc:
|
3
|
+
module Processors
|
4
|
+
module MiniMagickProcessor
|
5
|
+
def self.included(base)
|
6
|
+
base.send :extend, ClassMethods
|
7
|
+
base.alias_method_chain :process_attachment, :processing
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Yields a block containing an MiniMagick Image for the given binary data.
|
12
|
+
def with_image(file, &block)
|
13
|
+
begin
|
14
|
+
binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.from_file(file) unless !Object.const_defined?(:MiniMagick)
|
15
|
+
rescue
|
16
|
+
# Log the failure to load the image.
|
17
|
+
logger.debug("Exception working with image: #{$!}")
|
18
|
+
binary_data = nil
|
19
|
+
end
|
20
|
+
block.call binary_data if block && binary_data
|
21
|
+
ensure
|
22
|
+
!binary_data.nil?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
def process_attachment_with_processing
|
28
|
+
return unless process_attachment_without_processing
|
29
|
+
with_image do |img|
|
30
|
+
resize_image_or_thumbnail! img
|
31
|
+
self.width = img[:width] if respond_to?(:width)
|
32
|
+
self.height = img[:height] if respond_to?(:height)
|
33
|
+
callback_with_args :after_resize, img
|
34
|
+
end if image?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Performs the actual resizing operation for a thumbnail
|
38
|
+
def resize_image(img, size)
|
39
|
+
size = size.first if size.is_a?(Array) && size.length == 1
|
40
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
41
|
+
if size.is_a?(Fixnum)
|
42
|
+
size = [size, size]
|
43
|
+
img.resize(size.join('x'))
|
44
|
+
else
|
45
|
+
img.resize(size.join('x') + '!')
|
46
|
+
end
|
47
|
+
else
|
48
|
+
img.resize(size.to_s)
|
49
|
+
end
|
50
|
+
self.temp_path = img
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'RMagick'
|
2
|
+
module AttachmerbFu # :nodoc:
|
3
|
+
module Processors
|
4
|
+
module RmagickProcessor
|
5
|
+
def self.included(base)
|
6
|
+
base.send :extend, ClassMethods
|
7
|
+
base.alias_method_chain :process_attachment, :processing
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Yields a block containing an RMagick Image for the given binary data.
|
12
|
+
def with_image(file, &block)
|
13
|
+
begin
|
14
|
+
binary_data = file.is_a?(Magick::Image) ? file : Magick::Image.read(file).first unless !Object.const_defined?(:Magick)
|
15
|
+
rescue
|
16
|
+
# Log the failure to load the image. This should match ::Magick::ImageMagickError
|
17
|
+
# but that would cause acts_as_attachment to require rmagick.
|
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.columns if respond_to?(:width)
|
33
|
+
self.height = img.rows 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 && !size.first.is_a?(Fixnum)
|
41
|
+
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
42
|
+
size = [size, size] if size.is_a?(Fixnum)
|
43
|
+
img.thumbnail!(*size)
|
44
|
+
else
|
45
|
+
img.change_geometry(size.to_s) { |cols, rows, image| image.resize!(cols, rows) }
|
46
|
+
end
|
47
|
+
self.temp_path = write_to_temp_file(img.to_blob)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/geometry.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# This Geometry class was yanked from RMagick. However, it lets ImageMagick handle the actual change_geometry.
|
2
|
+
# Use #new_dimensions_for to get new dimensons
|
3
|
+
# Used so I can use spiffy RMagick geometry strings with ImageScience
|
4
|
+
class Geometry
|
5
|
+
# ! and @ are removed until support for them is added
|
6
|
+
FLAGS = ['', '%', '<', '>']#, '!', '@']
|
7
|
+
RFLAGS = { '%' => :percent,
|
8
|
+
'!' => :aspect,
|
9
|
+
'<' => :>,
|
10
|
+
'>' => :<,
|
11
|
+
'@' => :area }
|
12
|
+
|
13
|
+
attr_accessor :width, :height, :x, :y, :flag
|
14
|
+
|
15
|
+
def initialize(width=nil, height=nil, x=nil, y=nil, flag=nil)
|
16
|
+
# Support floating-point width and height arguments so Geometry
|
17
|
+
# objects can be used to specify Image#density= arguments.
|
18
|
+
raise ArgumentError, "width must be >= 0: #{width}" if width < 0
|
19
|
+
raise ArgumentError, "height must be >= 0: #{height}" if height < 0
|
20
|
+
@width = width.to_f
|
21
|
+
@height = height.to_f
|
22
|
+
@x = x.to_i
|
23
|
+
@y = y.to_i
|
24
|
+
@flag = flag
|
25
|
+
end
|
26
|
+
|
27
|
+
# Construct an object from a geometry string
|
28
|
+
RE = /\A(\d*)(?:x(\d+))?([-+]\d+)?([-+]\d+)?([%!<>@]?)\Z/
|
29
|
+
|
30
|
+
def self.from_s(str)
|
31
|
+
raise(ArgumentError, "no geometry string specified") unless str
|
32
|
+
|
33
|
+
if m = RE.match(str)
|
34
|
+
new(m[1].to_i, m[2].to_i, m[3].to_i, m[4].to_i, RFLAGS[m[5]])
|
35
|
+
else
|
36
|
+
raise ArgumentError, "invalid geometry format"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Convert object to a geometry string
|
41
|
+
def to_s
|
42
|
+
str = ''
|
43
|
+
str << "%g" % @width if @width > 0
|
44
|
+
str << 'x' if (@width > 0 || @height > 0)
|
45
|
+
str << "%g" % @height if @height > 0
|
46
|
+
str << "%+d%+d" % [@x, @y] if (@x != 0 || @y != 0)
|
47
|
+
str << FLAGS[@flag.to_i]
|
48
|
+
end
|
49
|
+
|
50
|
+
# attempts to get new dimensions for the current geometry string given these old dimensions.
|
51
|
+
# This doesn't implement the aspect flag (!) or the area flag (@). PDI
|
52
|
+
def new_dimensions_for(orig_width, orig_height)
|
53
|
+
new_width = orig_width
|
54
|
+
new_height = orig_height
|
55
|
+
|
56
|
+
case @flag
|
57
|
+
when :percent
|
58
|
+
scale_x = @width.zero? ? 100 : @width
|
59
|
+
scale_y = @height.zero? ? @width : @height
|
60
|
+
new_width = scale_x.to_f * (orig_width.to_f / 100.0)
|
61
|
+
new_height = scale_y.to_f * (orig_height.to_f / 100.0)
|
62
|
+
when :<, :>, nil
|
63
|
+
scale_factor =
|
64
|
+
if new_width.zero? || new_height.zero?
|
65
|
+
1.0
|
66
|
+
else
|
67
|
+
if @width.nonzero? && @height.nonzero?
|
68
|
+
[@width.to_f / new_width.to_f, @height.to_f / new_height.to_f].min
|
69
|
+
else
|
70
|
+
@width.nonzero? ? (@width.to_f / new_width.to_f) : (@height.to_f / new_height.to_f)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
new_width = scale_factor * new_width.to_f
|
74
|
+
new_height = scale_factor * new_height.to_f
|
75
|
+
new_width = orig_width if @flag && orig_width.send(@flag, new_width)
|
76
|
+
new_height = orig_height if @flag && orig_height.send(@flag, new_height)
|
77
|
+
end
|
78
|
+
|
79
|
+
[new_width, new_height].collect! { |v| v.round }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Array
|
84
|
+
# allows you to get new dimensions for the current array of dimensions with a given geometry string
|
85
|
+
#
|
86
|
+
# [50, 64] / '40>' # => [40, 51]
|
87
|
+
def /(geometry)
|
88
|
+
raise ArgumentError, "Only works with a [width, height] pair" if size != 2
|
89
|
+
raise ArgumentError, "Must pass a valid geometry string or object" unless geometry.is_a?(String) || geometry.is_a?(Geometry)
|
90
|
+
geometry = Geometry.from_s(geometry) if geometry.is_a?(String)
|
91
|
+
geometry.new_dimensions_for first, last
|
92
|
+
end
|
93
|
+
end
|
data/lib/tempfile_ext.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
Tempfile.class_eval do
|
4
|
+
# overwrite so tempfiles use the extension of the basename. important for rmagick and image science
|
5
|
+
def make_tmpname(basename, n)
|
6
|
+
ext = nil
|
7
|
+
sprintf("%s%d-%d%s", basename.to_s.gsub(/\.\w+$/) { |s| ext = s; '' }, $$, n, ext)
|
8
|
+
end
|
9
|
+
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,80 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
class FileSystemTest < Test::Unit::TestCase
|
4
|
+
include BaseAttachmentTests
|
5
|
+
attachment_model FileAttachment
|
6
|
+
|
7
|
+
def test_filesystem_size_for_file_attachment(klass = FileAttachment)
|
8
|
+
attachment_model klass
|
9
|
+
assert_created 1 do
|
10
|
+
attachment = upload_file :filename => '/files/rails.png'
|
11
|
+
assert_equal attachment.size, File.open(attachment.full_filename).stat.size
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
test_against_subclass :test_filesystem_size_for_file_attachment, FileAttachment
|
16
|
+
|
17
|
+
def test_should_not_overwrite_file_attachment(klass = FileAttachment)
|
18
|
+
attachment_model klass
|
19
|
+
assert_created 2 do
|
20
|
+
real = upload_file :filename => '/files/rails.png'
|
21
|
+
assert_valid real
|
22
|
+
assert !real.new_record?, real.errors.full_messages.join("\n")
|
23
|
+
assert !real.size.zero?
|
24
|
+
|
25
|
+
fake = upload_file :filename => '/files/fake/rails.png'
|
26
|
+
assert_valid fake
|
27
|
+
assert !fake.size.zero?
|
28
|
+
|
29
|
+
assert_not_equal File.open(real.full_filename).stat.size, File.open(fake.full_filename).stat.size
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
test_against_subclass :test_should_not_overwrite_file_attachment, FileAttachment
|
34
|
+
|
35
|
+
def test_should_store_file_attachment_in_filesystem(klass = FileAttachment)
|
36
|
+
attachment_model klass
|
37
|
+
attachment = nil
|
38
|
+
assert_created do
|
39
|
+
attachment = upload_file :filename => '/files/rails.png'
|
40
|
+
assert_valid attachment
|
41
|
+
assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
|
42
|
+
end
|
43
|
+
attachment
|
44
|
+
end
|
45
|
+
|
46
|
+
test_against_subclass :test_should_store_file_attachment_in_filesystem, FileAttachment
|
47
|
+
|
48
|
+
def test_should_delete_old_file_when_updating(klass = FileAttachment)
|
49
|
+
attachment_model klass
|
50
|
+
attachment = upload_file :filename => '/files/rails.png'
|
51
|
+
old_filename = attachment.full_filename
|
52
|
+
assert_not_created do
|
53
|
+
use_temp_file 'files/rails.png' do |file|
|
54
|
+
attachment.filename = 'rails2.png'
|
55
|
+
attachment.temp_path = File.join(fixture_path, file)
|
56
|
+
attachment.save!
|
57
|
+
assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
|
58
|
+
assert !File.exists?(old_filename), "#{old_filename} still exists"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
test_against_subclass :test_should_delete_old_file_when_updating, FileAttachment
|
64
|
+
|
65
|
+
def test_should_delete_old_file_when_renaming(klass = FileAttachment)
|
66
|
+
attachment_model klass
|
67
|
+
attachment = upload_file :filename => '/files/rails.png'
|
68
|
+
old_filename = attachment.full_filename
|
69
|
+
assert_not_created do
|
70
|
+
attachment.filename = 'rails2.png'
|
71
|
+
attachment.save
|
72
|
+
assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
|
73
|
+
assert !File.exists?(old_filename), "#{old_filename} still exists"
|
74
|
+
assert !attachment.reload.size.zero?
|
75
|
+
assert_equal 'rails2.png', attachment.filename
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
test_against_subclass :test_should_delete_old_file_when_renaming, FileAttachment
|
80
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
class S3Test < Test::Unit::TestCase
|
5
|
+
if File.exist?(File.join(File.dirname(__FILE__), '../../amazon_s3.yml'))
|
6
|
+
include BaseAttachmentTests
|
7
|
+
attachment_model S3Attachment
|
8
|
+
|
9
|
+
def test_should_create_correct_bucket_name(klass = S3Attachment)
|
10
|
+
attachment_model klass
|
11
|
+
attachment = upload_file :filename => '/files/rails.png'
|
12
|
+
assert_equal attachment.s3_config[:bucket_name], attachment.bucket_name
|
13
|
+
end
|
14
|
+
|
15
|
+
test_against_subclass :test_should_create_correct_bucket_name, S3Attachment
|
16
|
+
|
17
|
+
def test_should_create_default_path_prefix(klass = S3Attachment)
|
18
|
+
attachment_model klass
|
19
|
+
attachment = upload_file :filename => '/files/rails.png'
|
20
|
+
assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
|
21
|
+
end
|
22
|
+
|
23
|
+
test_against_subclass :test_should_create_default_path_prefix, S3Attachment
|
24
|
+
|
25
|
+
def test_should_create_custom_path_prefix(klass = S3WithPathPrefixAttachment)
|
26
|
+
attachment_model klass
|
27
|
+
attachment = upload_file :filename => '/files/rails.png'
|
28
|
+
assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
|
29
|
+
end
|
30
|
+
|
31
|
+
test_against_subclass :test_should_create_custom_path_prefix, S3WithPathPrefixAttachment
|
32
|
+
|
33
|
+
def test_should_create_valid_url(klass = S3Attachment)
|
34
|
+
attachment_model klass
|
35
|
+
attachment = upload_file :filename => '/files/rails.png'
|
36
|
+
assert_equal "#{s3_protocol}#{s3_hostname}#{s3_port_string}/#{attachment.bucket_name}/#{attachment.full_filename}", attachment.s3_url
|
37
|
+
end
|
38
|
+
|
39
|
+
test_against_subclass :test_should_create_valid_url, S3Attachment
|
40
|
+
|
41
|
+
def test_should_create_authenticated_url(klass = S3Attachment)
|
42
|
+
attachment_model klass
|
43
|
+
attachment = upload_file :filename => '/files/rails.png'
|
44
|
+
assert_match /^http.+AWSAccessKeyId.+Expires.+Signature.+/, attachment.authenticated_s3_url(:use_ssl => true)
|
45
|
+
end
|
46
|
+
|
47
|
+
test_against_subclass :test_should_create_authenticated_url, S3Attachment
|
48
|
+
|
49
|
+
def test_should_save_attachment(klass = S3Attachment)
|
50
|
+
attachment_model klass
|
51
|
+
assert_created do
|
52
|
+
attachment = upload_file :filename => '/files/rails.png'
|
53
|
+
assert_valid attachment
|
54
|
+
assert attachment.image?
|
55
|
+
assert !attachment.size.zero?
|
56
|
+
assert_kind_of Net::HTTPOK, http_response_for(attachment.s3_url)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test_against_subclass :test_should_save_attachment, S3Attachment
|
61
|
+
|
62
|
+
def test_should_delete_attachment_from_s3_when_attachment_record_destroyed(klass = S3Attachment)
|
63
|
+
attachment_model klass
|
64
|
+
attachment = upload_file :filename => '/files/rails.png'
|
65
|
+
|
66
|
+
urls = [attachment.s3_url] + attachment.thumbnails.collect(&:s3_url)
|
67
|
+
|
68
|
+
urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
|
69
|
+
attachment.destroy
|
70
|
+
urls.each do |url|
|
71
|
+
begin
|
72
|
+
http_response_for(url)
|
73
|
+
rescue Net::HTTPForbidden, Net::HTTPNotFound
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
test_against_subclass :test_should_delete_attachment_from_s3_when_attachment_record_destroyed, S3Attachment
|
80
|
+
|
81
|
+
protected
|
82
|
+
def http_response_for(url)
|
83
|
+
url = URI.parse(url)
|
84
|
+
Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
|
85
|
+
end
|
86
|
+
|
87
|
+
def s3_protocol
|
88
|
+
Technoweenie::AttachmentFu::Backends::S3Backend.protocol
|
89
|
+
end
|
90
|
+
|
91
|
+
def s3_hostname
|
92
|
+
Technoweenie::AttachmentFu::Backends::S3Backend.hostname
|
93
|
+
end
|
94
|
+
|
95
|
+
def s3_port_string
|
96
|
+
Technoweenie::AttachmentFu::Backends::S3Backend.port_string
|
97
|
+
end
|
98
|
+
else
|
99
|
+
def test_flunk_s3
|
100
|
+
puts "s3 config file not loaded, tests not running"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module BaseAttachmentTests
|
2
|
+
def test_should_create_file_from_uploaded_file
|
3
|
+
assert_created do
|
4
|
+
attachment = upload_file :filename => '/files/foo.txt'
|
5
|
+
assert_valid attachment
|
6
|
+
assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
|
7
|
+
assert attachment.image?
|
8
|
+
assert !attachment.size.zero?
|
9
|
+
#assert_equal 3, attachment.size
|
10
|
+
assert_nil attachment.width
|
11
|
+
assert_nil attachment.height
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_reassign_attribute_data
|
16
|
+
assert_created 1 do
|
17
|
+
attachment = upload_file :filename => '/files/rails.png'
|
18
|
+
assert_valid attachment
|
19
|
+
assert attachment.size > 0, "no data was set"
|
20
|
+
|
21
|
+
attachment.temp_data = 'wtf'
|
22
|
+
assert attachment.save_attachment?
|
23
|
+
attachment.save!
|
24
|
+
|
25
|
+
assert_equal 'wtf', attachment_model.find(attachment.id).send(:current_data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_no_reassign_attribute_data_on_nil
|
30
|
+
assert_created 1 do
|
31
|
+
attachment = upload_file :filename => '/files/rails.png'
|
32
|
+
assert_valid attachment
|
33
|
+
assert attachment.size > 0, "no data was set"
|
34
|
+
|
35
|
+
attachment.temp_data = nil
|
36
|
+
assert !attachment.save_attachment?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_should_overwrite_old_contents_when_updating
|
41
|
+
attachment = upload_file :filename => '/files/rails.png'
|
42
|
+
assert_not_created do # no new db_file records
|
43
|
+
use_temp_file 'files/rails.png' do |file|
|
44
|
+
attachment.filename = 'rails2.png'
|
45
|
+
attachment.temp_path = File.join(fixture_path, file)
|
46
|
+
attachment.save!
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_should_save_without_updating_file
|
52
|
+
attachment = upload_file :filename => '/files/foo.txt'
|
53
|
+
assert_valid attachment
|
54
|
+
assert !attachment.save_attachment?
|
55
|
+
assert_nothing_raised { attachment.save! }
|
56
|
+
end
|
57
|
+
end
|