jcnetdev-paperclip 1.0.20080704
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +26 -0
- data/README +48 -0
- data/README.rdoc +48 -0
- data/Rakefile +84 -0
- data/generators/paperclip/USAGE +5 -0
- data/generators/paperclip/paperclip_generator.rb +27 -0
- data/generators/paperclip/templates/paperclip_migration.rb +17 -0
- data/init.rb +1 -0
- data/lib/paperclip.rb +239 -0
- data/lib/paperclip/attachment.rb +243 -0
- data/lib/paperclip/geometry.rb +109 -0
- data/lib/paperclip/iostream.rb +43 -0
- data/lib/paperclip/storage.rb +179 -0
- data/lib/paperclip/thumbnail.rb +80 -0
- data/lib/paperclip/upfile.rb +33 -0
- data/paperclip.gemspec +55 -0
- data/rails/init.rb +1 -0
- data/tasks/paperclip_tasks.rake +38 -0
- data/test/.gitignore +1 -0
- data/test/database.yml +5 -0
- data/test/fixtures/12k.png +0 -0
- data/test/fixtures/50x50.png +0 -0
- data/test/fixtures/5k.png +0 -0
- data/test/fixtures/bad.png +1 -0
- data/test/fixtures/text.txt +0 -0
- data/test/helper.rb +44 -0
- data/test/test_attachment.rb +286 -0
- data/test/test_geometry.rb +142 -0
- data/test/test_integration.rb +331 -0
- data/test/test_iostream.rb +60 -0
- data/test/test_paperclip.rb +123 -0
- data/test/test_storage.rb +136 -0
- data/test/test_thumbnail.rb +107 -0
- metadata +93 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# Handles thumbnailing images that are uploaded.
|
3
|
+
class Thumbnail
|
4
|
+
|
5
|
+
attr_accessor :file, :current_geometry, :target_geometry, :format, :whiny_thumbnails
|
6
|
+
|
7
|
+
# Creates a Thumbnail object set to work on the +file+ given. It
|
8
|
+
# will attempt to transform the image into one defined by +target_geometry+
|
9
|
+
# which is a "WxH"-style string. +format+ will be inferred from the +file+
|
10
|
+
# unless specified. Thumbnail creation will raise no errors unless
|
11
|
+
# +whiny_thumbnails+ is true (which it is, by default.
|
12
|
+
def initialize file, target_geometry, format = nil, whiny_thumbnails = true
|
13
|
+
@file = file
|
14
|
+
@crop = target_geometry[-1,1] == '#'
|
15
|
+
@target_geometry = Geometry.parse target_geometry
|
16
|
+
@current_geometry = Geometry.from_file file
|
17
|
+
@whiny_thumbnails = whiny_thumbnails
|
18
|
+
|
19
|
+
@current_format = File.extname(@file.path)
|
20
|
+
@basename = File.basename(@file.path, @current_format)
|
21
|
+
|
22
|
+
@format = format
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a thumbnail, as specified in +initialize+, +make+s it, and returns the
|
26
|
+
# resulting Tempfile.
|
27
|
+
def self.make file, dimensions, format = nil, whiny_thumbnails = true
|
28
|
+
new(file, dimensions, format, whiny_thumbnails).make
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns true if the +target_geometry+ is meant to crop.
|
32
|
+
def crop?
|
33
|
+
@crop
|
34
|
+
end
|
35
|
+
|
36
|
+
# Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile
|
37
|
+
# that contains the new image.
|
38
|
+
def make
|
39
|
+
src = @file
|
40
|
+
dst = Tempfile.new([@basename, @format].compact.join("."))
|
41
|
+
dst.binmode
|
42
|
+
|
43
|
+
command = <<-end_command
|
44
|
+
#{ Paperclip.path_for_command('convert') }
|
45
|
+
"#{ File.expand_path(src.path) }"
|
46
|
+
#{ transformation_command }
|
47
|
+
"#{ File.expand_path(dst.path) }"
|
48
|
+
end_command
|
49
|
+
success = system(command.gsub(/\s+/, " "))
|
50
|
+
|
51
|
+
if success && $?.exitstatus != 0 && @whiny_thumbnails
|
52
|
+
raise PaperclipError, "There was an error processing this thumbnail"
|
53
|
+
end
|
54
|
+
|
55
|
+
dst
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the command ImageMagick's +convert+ needs to transform the image
|
59
|
+
# into the thumbnail.
|
60
|
+
def transformation_command
|
61
|
+
scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
|
62
|
+
trans = "-scale \"#{scale}\""
|
63
|
+
trans << " -crop \"#{crop}\" +repage" if crop
|
64
|
+
trans
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Due to how ImageMagick handles its image format conversion and how Tempfile
|
69
|
+
# handles its naming scheme, it is necessary to override how Tempfile makes
|
70
|
+
# its names so as to allow for file extensions. Idea taken from the comments
|
71
|
+
# on this blog post:
|
72
|
+
# http://marsorange.com/archives/of-mogrify-ruby-tempfile-dynamic-class-definitions
|
73
|
+
class Tempfile < ::Tempfile
|
74
|
+
# Replaces Tempfile's +make_tmpname+ with one that honors file extensions.
|
75
|
+
def make_tmpname(basename, n)
|
76
|
+
extension = File.extname(basename)
|
77
|
+
sprintf("%s,%d,%d%s", File.basename(basename, extension), $$, n, extension)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# The Upfile module is a convenience module for adding uploaded-file-type methods
|
3
|
+
# to the +File+ class. Useful for testing.
|
4
|
+
# user.avatar = File.new("test/test_avatar.jpg")
|
5
|
+
module Upfile
|
6
|
+
|
7
|
+
# Infer the MIME-type of the file from the extension.
|
8
|
+
def content_type
|
9
|
+
type = self.path.match(/\.(\w+)$/)[1] rescue "octet-stream"
|
10
|
+
case type
|
11
|
+
when "jpg", "png", "gif" then "image/#{type}"
|
12
|
+
when "txt" then "text/plain"
|
13
|
+
when "csv", "xml", "html", "htm", "css", "js" then "text/#{type}"
|
14
|
+
else "x-application/#{type}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the file's normal name.
|
19
|
+
def original_filename
|
20
|
+
File.basename(self.path)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the size of the file.
|
24
|
+
def size
|
25
|
+
File.size(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class File #:nodoc:
|
32
|
+
include Paperclip::Upfile
|
33
|
+
end
|
data/paperclip.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'paperclip'
|
3
|
+
s.version = '1.0.20080704'
|
4
|
+
s.date = '2008-07-04'
|
5
|
+
|
6
|
+
s.summary = "Allows easy file uploading for Rails"
|
7
|
+
s.description = "Paperclip is intended as an easy file attachment library for ActiveRecord. The intent behind it was to keep setup as easy as possible and to treat files as much like other attributes as possible. This means they aren't saved to their final locations on disk, nor are they deleted if set to nil, until ActiveRecord::Base#save is called. It manages validations based on size and presence, if required. It can transform its assigned image into thumbnails if needed, and the prerequisites are as simple as installing ImageMagick (which, for most modern Unix-based systems, is as easy as installing the right packages). Attached files are saved to the filesystem and referenced in the browser by an easily understandable specification, which has sensible and useful defaults."
|
8
|
+
|
9
|
+
s.authors = ['Jon Yurek']
|
10
|
+
s.email = 'info@thoughtbot.com'
|
11
|
+
s.homepage = 'http://github.com/thoughtbot/paperclip'
|
12
|
+
|
13
|
+
s.has_rdoc = true
|
14
|
+
s.rdoc_options = ["--main", "README"]
|
15
|
+
s.extra_rdoc_files = ["README"]
|
16
|
+
|
17
|
+
s.add_dependency 'rails', ['>= 2.1']
|
18
|
+
|
19
|
+
s.files = ["LICENSE",
|
20
|
+
"README",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"generators/paperclip/paperclip_generator.rb",
|
24
|
+
"generators/paperclip/templates/paperclip_migration.rb",
|
25
|
+
"generators/paperclip/USAGE",
|
26
|
+
"init.rb",
|
27
|
+
"lib/paperclip/attachment.rb",
|
28
|
+
"lib/paperclip/geometry.rb",
|
29
|
+
"lib/paperclip/iostream.rb",
|
30
|
+
"lib/paperclip/storage.rb",
|
31
|
+
"lib/paperclip/thumbnail.rb",
|
32
|
+
"lib/paperclip/upfile.rb",
|
33
|
+
"lib/paperclip.rb",
|
34
|
+
"paperclip.gemspec",
|
35
|
+
"rails/init.rb",
|
36
|
+
"tasks/paperclip_tasks.rake"]
|
37
|
+
|
38
|
+
s.test_files = ["test/.gitignore",
|
39
|
+
"test/database.yml",
|
40
|
+
"test/fixtures/12k.png",
|
41
|
+
"test/fixtures/50x50.png",
|
42
|
+
"test/fixtures/5k.png",
|
43
|
+
"test/fixtures/bad.png",
|
44
|
+
"test/fixtures/text.txt",
|
45
|
+
"test/helper.rb",
|
46
|
+
"test/test_attachment.rb",
|
47
|
+
"test/test_geometry.rb",
|
48
|
+
"test/test_integration.rb",
|
49
|
+
"test/test_iostream.rb",
|
50
|
+
"test/test_paperclip.rb",
|
51
|
+
"test/test_storage.rb",
|
52
|
+
"test/test_thumbnail.rb"]
|
53
|
+
|
54
|
+
end
|
55
|
+
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'paperclip'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
def obtain_class
|
2
|
+
class_name = ENV['CLASS'] || ENV['class']
|
3
|
+
raise "Must specify CLASS" unless class_name
|
4
|
+
@klass = Object.const_get(class_name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def obtain_attachments
|
8
|
+
name = ENV['ATTACHMENT'] || ENV['attachment']
|
9
|
+
raise "Class #{@klass.name} has no attachments specified" unless @klass.respond_to?(:attachment_definitions)
|
10
|
+
if !name.blank? && @klass.attachment_definitions.keys.include?(name)
|
11
|
+
[ name ]
|
12
|
+
else
|
13
|
+
@klass.attachment_definitions.keys
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :paperclip do
|
18
|
+
desc "Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)"
|
19
|
+
task :refresh => :environment do
|
20
|
+
klass = obtain_class
|
21
|
+
names = obtain_attachments
|
22
|
+
instances = klass.find(:all)
|
23
|
+
|
24
|
+
puts "Regenerating thumbnails for #{instances.length} instances of #{klass.name}:"
|
25
|
+
instances.each do |instance|
|
26
|
+
names.each do |name|
|
27
|
+
result = if instance.send("#{ name }?")
|
28
|
+
instance.send(name).reprocess!
|
29
|
+
instance.send(name).save
|
30
|
+
else
|
31
|
+
true
|
32
|
+
end
|
33
|
+
print result ? "." : "x"; $stdout.flush
|
34
|
+
end
|
35
|
+
end
|
36
|
+
puts " Done."
|
37
|
+
end
|
38
|
+
end
|
data/test/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
debug.log
|
data/test/database.yml
ADDED
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
This is not an image.
|
File without changes
|
data/test/helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'mocha'
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
require 'active_record'
|
8
|
+
begin
|
9
|
+
require 'ruby-debug'
|
10
|
+
rescue LoadError
|
11
|
+
puts "ruby-debug not loaded"
|
12
|
+
end
|
13
|
+
|
14
|
+
ROOT = File.join(File.dirname(__FILE__), '..')
|
15
|
+
RAILS_ROOT = ROOT
|
16
|
+
|
17
|
+
$LOAD_PATH << File.join(ROOT, 'lib')
|
18
|
+
$LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
|
19
|
+
|
20
|
+
require File.join(ROOT, 'lib', 'paperclip.rb')
|
21
|
+
|
22
|
+
ENV['RAILS_ENV'] ||= 'test'
|
23
|
+
|
24
|
+
FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
|
25
|
+
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
26
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
27
|
+
ActiveRecord::Base.establish_connection(config[ENV['RAILS_ENV'] || 'test'])
|
28
|
+
|
29
|
+
def rebuild_model options = {}
|
30
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
|
31
|
+
table.column :other, :string
|
32
|
+
table.column :avatar_file_name, :string
|
33
|
+
table.column :avatar_content_type, :string
|
34
|
+
table.column :avatar_file_size, :integer
|
35
|
+
end
|
36
|
+
|
37
|
+
ActiveRecord::Base.send(:include, Paperclip)
|
38
|
+
Object.send(:remove_const, "Dummy") rescue nil
|
39
|
+
Object.const_set("Dummy", Class.new(ActiveRecord::Base))
|
40
|
+
Dummy.class_eval do
|
41
|
+
include Paperclip
|
42
|
+
has_attached_file :avatar, options
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,286 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class Dummy
|
4
|
+
# This is a dummy class
|
5
|
+
end
|
6
|
+
|
7
|
+
class AttachmentTest < Test::Unit::TestCase
|
8
|
+
context "Attachment default_options" do
|
9
|
+
setup do
|
10
|
+
rebuild_model
|
11
|
+
@old_default_options = Paperclip::Attachment.default_options.dup
|
12
|
+
@new_default_options = @old_default_options.merge({
|
13
|
+
:path => "argle/bargle",
|
14
|
+
:url => "fooferon",
|
15
|
+
:default_url => "not here.png"
|
16
|
+
})
|
17
|
+
end
|
18
|
+
|
19
|
+
teardown do
|
20
|
+
Paperclip::Attachment.default_options.merge! @old_default_options
|
21
|
+
end
|
22
|
+
|
23
|
+
should "be overrideable" do
|
24
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
25
|
+
@new_default_options.keys.each do |key|
|
26
|
+
assert_equal @new_default_options[key],
|
27
|
+
Paperclip::Attachment.default_options[key]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "without an Attachment" do
|
32
|
+
setup do
|
33
|
+
@dummy = Dummy.new
|
34
|
+
end
|
35
|
+
|
36
|
+
should "return false when asked exists?" do
|
37
|
+
assert !@dummy.avatar.exists?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "on an Attachment" do
|
42
|
+
setup do
|
43
|
+
@dummy = Dummy.new
|
44
|
+
@attachment = @dummy.avatar
|
45
|
+
end
|
46
|
+
|
47
|
+
Paperclip::Attachment.default_options.keys.each do |key|
|
48
|
+
should "be the default_options for #{key}" do
|
49
|
+
assert_equal @old_default_options[key],
|
50
|
+
@attachment.instance_variable_get("@#{key}"),
|
51
|
+
key
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when redefined" do
|
56
|
+
setup do
|
57
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
58
|
+
@dummy = Dummy.new
|
59
|
+
@attachment = @dummy.avatar
|
60
|
+
end
|
61
|
+
|
62
|
+
Paperclip::Attachment.default_options.keys.each do |key|
|
63
|
+
should "be the new default_options for #{key}" do
|
64
|
+
assert_equal @new_default_options[key],
|
65
|
+
@attachment.instance_variable_get("@#{key}"),
|
66
|
+
key
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "An attachment with similarly named interpolations" do
|
74
|
+
setup do
|
75
|
+
rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
|
76
|
+
@dummy = Dummy.new
|
77
|
+
@dummy.stubs(:id).returns(1024)
|
78
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
79
|
+
"fixtures",
|
80
|
+
"5k.png"))
|
81
|
+
@dummy.avatar = @file
|
82
|
+
end
|
83
|
+
|
84
|
+
should "make sure that they are interpolated correctly" do
|
85
|
+
assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "Assigning an attachment" do
|
90
|
+
setup do
|
91
|
+
rebuild_model
|
92
|
+
|
93
|
+
@not_file = mock
|
94
|
+
@not_file.stubs(:nil?).returns(false)
|
95
|
+
@not_file.expects(:to_tempfile).returns(self)
|
96
|
+
@not_file.expects(:original_filename).returns("filename.png\r\n")
|
97
|
+
@not_file.expects(:content_type).returns("image/png\r\n")
|
98
|
+
@not_file.expects(:size).returns(10)
|
99
|
+
|
100
|
+
@dummy = Dummy.new
|
101
|
+
@attachment = @dummy.avatar
|
102
|
+
@attachment.expects(:valid_assignment?).with(@not_file).returns(true)
|
103
|
+
@attachment.expects(:queue_existing_for_delete)
|
104
|
+
@attachment.expects(:post_process)
|
105
|
+
@attachment.expects(:validate)
|
106
|
+
@dummy.avatar = @not_file
|
107
|
+
end
|
108
|
+
|
109
|
+
should "strip whitespace from original_filename field" do
|
110
|
+
assert_equal "filename.png", @dummy.avatar.original_filename
|
111
|
+
end
|
112
|
+
|
113
|
+
should "strip whitespace from content_type field" do
|
114
|
+
assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
context "Attachment with strange letters" do
|
120
|
+
setup do
|
121
|
+
rebuild_model
|
122
|
+
|
123
|
+
@not_file = mock
|
124
|
+
@not_file.stubs(:nil?).returns(false)
|
125
|
+
@not_file.expects(:to_tempfile).returns(self)
|
126
|
+
@not_file.expects(:original_filename).returns("sheep_say_bæ.png\r\n")
|
127
|
+
@not_file.expects(:content_type).returns("image/png\r\n")
|
128
|
+
@not_file.expects(:size).returns(10)
|
129
|
+
|
130
|
+
@dummy = Dummy.new
|
131
|
+
@attachment = @dummy.avatar
|
132
|
+
@attachment.expects(:valid_assignment?).with(@not_file).returns(true)
|
133
|
+
@attachment.expects(:queue_existing_for_delete)
|
134
|
+
@attachment.expects(:post_process)
|
135
|
+
@attachment.expects(:validate)
|
136
|
+
@dummy.avatar = @not_file
|
137
|
+
end
|
138
|
+
|
139
|
+
should "remove strange letters and replace with underscore (_)" do
|
140
|
+
assert_equal "sheep_say_b_.png", @dummy.avatar.original_filename
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
context "An attachment" do
|
146
|
+
setup do
|
147
|
+
Paperclip::Attachment.default_options.merge!({
|
148
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
149
|
+
})
|
150
|
+
FileUtils.rm_rf("tmp")
|
151
|
+
@instance = stub
|
152
|
+
@instance.stubs(:id).returns(41)
|
153
|
+
@instance.stubs(:class).returns(Dummy)
|
154
|
+
@instance.stubs(:[]).with(:test_file_name).returns(nil)
|
155
|
+
@instance.stubs(:[]).with(:test_content_type).returns(nil)
|
156
|
+
@instance.stubs(:[]).with(:test_file_size).returns(nil)
|
157
|
+
@attachment = Paperclip::Attachment.new(:test,
|
158
|
+
@instance)
|
159
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
160
|
+
"fixtures",
|
161
|
+
"5k.png"))
|
162
|
+
end
|
163
|
+
|
164
|
+
should "return its default_url when no file assigned" do
|
165
|
+
assert @attachment.to_file.nil?
|
166
|
+
assert_equal "/tests/original/missing.png", @attachment.url
|
167
|
+
assert_equal "/tests/blah/missing.png", @attachment.url(:blah)
|
168
|
+
end
|
169
|
+
|
170
|
+
context "with a file assigned in the database" do
|
171
|
+
setup do
|
172
|
+
@instance.stubs(:[]).with(:test_file_name).returns("5k.png")
|
173
|
+
@instance.stubs(:[]).with(:test_content_type).returns("image/png")
|
174
|
+
@instance.stubs(:[]).with(:test_file_size).returns(12345)
|
175
|
+
end
|
176
|
+
|
177
|
+
should "return a correct url even if the file does not exist" do
|
178
|
+
assert_nil @attachment.to_file
|
179
|
+
assert_equal "/tests/41/blah/5k.png", @attachment.url(:blah)
|
180
|
+
end
|
181
|
+
|
182
|
+
should "return the proper path when filename has a single .'s" do
|
183
|
+
assert_equal "./test/../tmp/tests/dummies/original/41/5k.png", @attachment.path
|
184
|
+
end
|
185
|
+
|
186
|
+
should "return the proper path when filename has multiple .'s" do
|
187
|
+
@instance.stubs(:[]).with(:test_file_name).returns("5k.old.png")
|
188
|
+
assert_equal "./test/../tmp/tests/dummies/original/41/5k.old.png", @attachment.path
|
189
|
+
end
|
190
|
+
|
191
|
+
context "when expecting three styles" do
|
192
|
+
setup do
|
193
|
+
styles = {:styles => { :large => ["400x400", :png],
|
194
|
+
:medium => ["100x100", :gif],
|
195
|
+
:small => ["32x32#", :jpg]}}
|
196
|
+
@attachment = Paperclip::Attachment.new(:test,
|
197
|
+
@instance,
|
198
|
+
styles)
|
199
|
+
end
|
200
|
+
|
201
|
+
context "and assigned a file" do
|
202
|
+
setup do
|
203
|
+
@instance.expects(:[]=).with(:test_file_name,
|
204
|
+
File.basename(@file.path))
|
205
|
+
@instance.expects(:[]=).with(:test_content_type, "image/png")
|
206
|
+
@instance.expects(:[]=).with(:test_file_size, @file.size)
|
207
|
+
@instance.expects(:[]=).with(:test_file_name, nil)
|
208
|
+
@instance.expects(:[]=).with(:test_content_type, nil)
|
209
|
+
@instance.expects(:[]=).with(:test_file_size, nil)
|
210
|
+
@attachment.assign(@file)
|
211
|
+
end
|
212
|
+
|
213
|
+
should "be dirty" do
|
214
|
+
assert @attachment.dirty?
|
215
|
+
end
|
216
|
+
|
217
|
+
context "and saved" do
|
218
|
+
setup do
|
219
|
+
@attachment.save
|
220
|
+
end
|
221
|
+
|
222
|
+
should "return the real url" do
|
223
|
+
assert @attachment.to_file
|
224
|
+
assert_equal "/tests/41/original/5k.png", @attachment.url
|
225
|
+
assert_equal "/tests/41/small/5k.jpg", @attachment.url(:small)
|
226
|
+
end
|
227
|
+
|
228
|
+
should "commit the files to disk" do
|
229
|
+
[:large, :medium, :small].each do |style|
|
230
|
+
io = @attachment.to_io(style)
|
231
|
+
assert File.exists?(io)
|
232
|
+
assert ! io.is_a?(::Tempfile)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
should "save the files as the right formats and sizes" do
|
237
|
+
[[:large, 400, 61, "PNG"],
|
238
|
+
[:medium, 100, 15, "GIF"],
|
239
|
+
[:small, 32, 32, "JPEG"]].each do |style|
|
240
|
+
cmd = "identify -format '%w %h %b %m' " +
|
241
|
+
"#{@attachment.to_io(style.first).path}"
|
242
|
+
out = `#{cmd}`
|
243
|
+
width, height, size, format = out.split(" ")
|
244
|
+
assert_equal style[1].to_s, width.to_s
|
245
|
+
assert_equal style[2].to_s, height.to_s
|
246
|
+
assert_equal style[3].to_s, format.to_s
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
should "still have its #file attribute not be nil" do
|
251
|
+
assert ! @attachment.to_file.nil?
|
252
|
+
end
|
253
|
+
|
254
|
+
context "and deleted" do
|
255
|
+
setup do
|
256
|
+
@existing_names = @attachment.styles.keys.collect do |style|
|
257
|
+
@attachment.path(style)
|
258
|
+
end
|
259
|
+
@instance.expects(:[]=).with(:test_file_name, nil)
|
260
|
+
@instance.expects(:[]=).with(:test_content_type, nil)
|
261
|
+
@instance.expects(:[]=).with(:test_file_size, nil)
|
262
|
+
@attachment.assign nil
|
263
|
+
@attachment.save
|
264
|
+
end
|
265
|
+
|
266
|
+
should "delete the files" do
|
267
|
+
@existing_names.each{|f| assert ! File.exists?(f) }
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
context "when trying a nonexistant storage type" do
|
277
|
+
setup do
|
278
|
+
rebuild_model :storage => :not_here
|
279
|
+
end
|
280
|
+
|
281
|
+
should "not be able to find the module" do
|
282
|
+
assert_raise(NameError){ Dummy.new.avatar }
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|