ioquatix-attachment_fu 1.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/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/rails/init.rb ADDED
@@ -0,0 +1,16 @@
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
10
+
11
+ require 'geometry'
12
+ ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
13
+ Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
14
+ FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
15
+
16
+ $:.unshift(File.dirname(__FILE__) + '/vendor')
@@ -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_paths.unshift 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,119 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2
+ require 'net/http'
3
+
4
+ class S3Test < Test::Unit::TestCase
5
+ def self.test_S3?
6
+ true unless ENV["TEST_S3"] == "false"
7
+ end
8
+
9
+ if test_S3? && File.exist?(File.join(File.dirname(__FILE__), '../../amazon_s3.yml'))
10
+ include BaseAttachmentTests
11
+ attachment_model S3Attachment
12
+
13
+ def test_should_create_correct_bucket_name(klass = S3Attachment)
14
+ attachment_model klass
15
+ attachment = upload_file :filename => '/files/rails.png'
16
+ assert_equal attachment.s3_config[:bucket_name], attachment.bucket_name
17
+ end
18
+
19
+ test_against_subclass :test_should_create_correct_bucket_name, S3Attachment
20
+
21
+ def test_should_create_default_path_prefix(klass = S3Attachment)
22
+ attachment_model klass
23
+ attachment = upload_file :filename => '/files/rails.png'
24
+ assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
25
+ end
26
+
27
+ test_against_subclass :test_should_create_default_path_prefix, S3Attachment
28
+
29
+ def test_should_create_custom_path_prefix(klass = S3WithPathPrefixAttachment)
30
+ attachment_model klass
31
+ attachment = upload_file :filename => '/files/rails.png'
32
+ assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
33
+ end
34
+
35
+ test_against_subclass :test_should_create_custom_path_prefix, S3WithPathPrefixAttachment
36
+
37
+ def test_should_create_valid_url(klass = S3Attachment)
38
+ attachment_model klass
39
+ attachment = upload_file :filename => '/files/rails.png'
40
+ assert_equal "#{s3_protocol}#{s3_hostname}#{s3_port_string}/#{attachment.bucket_name}/#{attachment.full_filename}", attachment.s3_url
41
+ end
42
+
43
+ test_against_subclass :test_should_create_valid_url, S3Attachment
44
+
45
+ def test_should_create_authenticated_url(klass = S3Attachment)
46
+ attachment_model klass
47
+ attachment = upload_file :filename => '/files/rails.png'
48
+ assert_match /^http.+AWSAccessKeyId.+Expires.+Signature.+/, attachment.authenticated_s3_url(:use_ssl => true)
49
+ end
50
+
51
+ test_against_subclass :test_should_create_authenticated_url, S3Attachment
52
+
53
+ def test_should_create_authenticated_url_for_thumbnail(klass = S3Attachment)
54
+ attachment_model klass
55
+ attachment = upload_file :filename => '/files/rails.png'
56
+ ['large', :large].each do |thumbnail|
57
+ assert_match(
58
+ /^http.+rails_large\.png.+AWSAccessKeyId.+Expires.+Signature/,
59
+ attachment.authenticated_s3_url(thumbnail),
60
+ "authenticated_s3_url failed with #{thumbnail.class} parameter"
61
+ )
62
+ end
63
+ end
64
+
65
+ def test_should_save_attachment(klass = S3Attachment)
66
+ attachment_model klass
67
+ assert_created do
68
+ attachment = upload_file :filename => '/files/rails.png'
69
+ assert_valid attachment
70
+ assert attachment.image?
71
+ assert !attachment.size.zero?
72
+ assert_kind_of Net::HTTPOK, http_response_for(attachment.s3_url)
73
+ end
74
+ end
75
+
76
+ test_against_subclass :test_should_save_attachment, S3Attachment
77
+
78
+ def test_should_delete_attachment_from_s3_when_attachment_record_destroyed(klass = S3Attachment)
79
+ attachment_model klass
80
+ attachment = upload_file :filename => '/files/rails.png'
81
+
82
+ urls = [attachment.s3_url] + attachment.thumbnails.collect(&:s3_url)
83
+
84
+ urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
85
+ attachment.destroy
86
+ urls.each do |url|
87
+ begin
88
+ http_response_for(url)
89
+ rescue Net::HTTPForbidden, Net::HTTPNotFound
90
+ nil
91
+ end
92
+ end
93
+ end
94
+
95
+ test_against_subclass :test_should_delete_attachment_from_s3_when_attachment_record_destroyed, S3Attachment
96
+
97
+ protected
98
+ def http_response_for(url)
99
+ url = URI.parse(url)
100
+ Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
101
+ end
102
+
103
+ def s3_protocol
104
+ Technoweenie::AttachmentFu::Backends::S3Backend.protocol
105
+ end
106
+
107
+ def s3_hostname
108
+ Technoweenie::AttachmentFu::Backends::S3Backend.hostname
109
+ end
110
+
111
+ def s3_port_string
112
+ Technoweenie::AttachmentFu::Backends::S3Backend.port_string
113
+ end
114
+ else
115
+ def test_flunk_s3
116
+ puts "s3 config file not loaded, tests not running"
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,77 @@
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_should_create_file_from_merb_temp_file
16
+ assert_created do
17
+ attachment = upload_merb_file :filename => '/files/foo.txt'
18
+ assert_valid attachment
19
+ assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
20
+ assert attachment.image?
21
+ assert !attachment.size.zero?
22
+ #assert_equal 3, attachment.size
23
+ assert_nil attachment.width
24
+ assert_nil attachment.height
25
+ end
26
+ end
27
+
28
+ def test_reassign_attribute_data
29
+ assert_created 1 do
30
+ attachment = upload_file :filename => '/files/rails.png'
31
+ assert_valid attachment
32
+ assert attachment.size > 0, "no data was set"
33
+
34
+ attachment.set_temp_data 'wtf'
35
+ assert attachment.save_attachment?
36
+ attachment.save!
37
+
38
+ assert_equal 'wtf', attachment_model.find(attachment.id).send(:current_data)
39
+ end
40
+ end
41
+
42
+ def test_no_reassign_attribute_data_on_nil
43
+ assert_created 1 do
44
+ attachment = upload_file :filename => '/files/rails.png'
45
+ assert_valid attachment
46
+ assert attachment.size > 0, "no data was set"
47
+
48
+ attachment.set_temp_data nil
49
+ assert !attachment.save_attachment?
50
+ end
51
+ end
52
+
53
+ def test_should_overwrite_old_contents_when_updating
54
+ attachment = upload_file :filename => '/files/rails.png'
55
+ assert_not_created do # no new db_file records
56
+ use_temp_file 'files/rails.png' do |file|
57
+ attachment.filename = 'rails2.png'
58
+ attachment.temp_paths.unshift File.join(fixture_path, file)
59
+ attachment.save!
60
+ end
61
+ end
62
+ end
63
+
64
+ def test_should_save_without_updating_file
65
+ attachment = upload_file :filename => '/files/foo.txt'
66
+ assert_valid attachment
67
+ assert !attachment.save_attachment?
68
+ assert_nothing_raised { attachment.save! }
69
+ end
70
+
71
+ def test_should_handle_nil_file_upload
72
+ attachment = attachment_model.create :uploaded_data => ''
73
+ assert_raise ActiveRecord::RecordInvalid do
74
+ attachment.save!
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,70 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class BasicTest < Test::Unit::TestCase
4
+ def test_should_set_default_min_size
5
+ assert_equal 1, Attachment.attachment_options[:min_size]
6
+ end
7
+
8
+ def test_should_set_default_max_size
9
+ assert_equal 1.megabyte, Attachment.attachment_options[:max_size]
10
+ end
11
+
12
+ def test_should_set_default_size
13
+ assert_equal (1..1.megabyte), Attachment.attachment_options[:size]
14
+ end
15
+
16
+ def test_should_set_default_thumbnails_option
17
+ assert_equal Hash.new, Attachment.attachment_options[:thumbnails]
18
+ end
19
+
20
+ def test_should_set_default_thumbnail_class
21
+ assert_equal Attachment, Attachment.attachment_options[:thumbnail_class]
22
+ end
23
+
24
+ def test_should_normalize_content_types_to_array
25
+ assert_equal %w(pdf), PdfAttachment.attachment_options[:content_type]
26
+ assert_equal %w(pdf doc txt), DocAttachment.attachment_options[:content_type]
27
+ assert_equal ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg'], ImageAttachment.attachment_options[:content_type]
28
+ assert_equal ['pdf', 'image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg'], ImageOrPdfAttachment.attachment_options[:content_type]
29
+ end
30
+
31
+ def test_should_sanitize_content_type
32
+ @attachment = Attachment.new :content_type => ' foo '
33
+ assert_equal 'foo', @attachment.content_type
34
+ end
35
+
36
+ def test_should_sanitize_filenames
37
+ @attachment = Attachment.new :filename => 'blah/foo.bar'
38
+ assert_equal 'foo.bar', @attachment.filename
39
+
40
+ @attachment.filename = 'blah\\foo.bar'
41
+ assert_equal 'foo.bar', @attachment.filename
42
+
43
+ @attachment.filename = 'f o!O-.bar'
44
+ assert_equal 'f_o_O-.bar', @attachment.filename
45
+
46
+ @attachment.filename = 'sheeps_says_bææ'
47
+ assert_equal 'sheeps_says_b__', @attachment.filename
48
+
49
+ @attachment.filename = nil
50
+ assert_nil @attachment.filename
51
+ end
52
+
53
+ def test_should_convert_thumbnail_name
54
+ @attachment = FileAttachment.new :filename => 'foo.bar'
55
+ assert_equal 'foo.bar', @attachment.thumbnail_name_for(nil)
56
+ assert_equal 'foo.bar', @attachment.thumbnail_name_for('')
57
+ assert_equal 'foo_blah.bar', @attachment.thumbnail_name_for(:blah)
58
+ assert_equal 'foo_blah.blah.bar', @attachment.thumbnail_name_for('blah.blah')
59
+
60
+ @attachment.filename = 'foo.bar.baz'
61
+ assert_equal 'foo.bar_blah.baz', @attachment.thumbnail_name_for(:blah)
62
+ end
63
+
64
+ def test_should_require_valid_thumbnails_option
65
+ klass = Class.new(ActiveRecord::Base)
66
+ assert_raise ArgumentError do
67
+ klass.has_attachment :thumbnails => []
68
+ end
69
+ end
70
+ end