Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
paperclip
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ikcrm_common
paperclip
Commits
f79dadce
Commit
f79dadce
authored
Apr 21, 2008
by
Jon Yurek
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://github.com/mvanholstyn/paperclip
into mvanholstyn/master
parents
22b4c0c2
1fcf1d7e
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
118 additions
and
89 deletions
+118
-89
.gitignore
+1
-0
lib/paperclip.rb
+2
-2
lib/paperclip/attachment.rb
+14
-30
lib/paperclip/iostream.rb
+1
-1
lib/paperclip/storage.rb
+38
-28
test/test_attachment.rb
+40
-18
test/test_integration.rb
+22
-6
test/test_storage.rb
+0
-4
No files found.
.gitignore
View file @
f79dadce
*~
*.swp
*.swp
tmp
tmp
s3.yml
s3.yml
lib/paperclip.rb
View file @
f79dadce
...
@@ -131,7 +131,7 @@ module Paperclip
...
@@ -131,7 +131,7 @@ module Paperclip
end
end
define_method
"
#{
name
}
?"
do
define_method
"
#{
name
}
?"
do
!
attachment_for
(
name
).
file
.
nil
?
!
attachment_for
(
name
).
original_filename
.
blank
?
end
end
validates_each
(
name
)
do
|
record
,
attr
,
value
|
validates_each
(
name
)
do
|
record
,
attr
,
value
|
...
@@ -161,7 +161,7 @@ module Paperclip
...
@@ -161,7 +161,7 @@ module Paperclip
# Places ActiveRecord-style validations on the presence of a file.
# Places ActiveRecord-style validations on the presence of a file.
def
validates_attachment_presence
name
def
validates_attachment_presence
name
attachment_definitions
[
name
][
:validations
]
<<
lambda
do
|
attachment
,
instance
|
attachment_definitions
[
name
][
:validations
]
<<
lambda
do
|
attachment
,
instance
|
if
attachment
.
file
.
nil?
||
!
File
.
exist?
(
attachment
.
file
.
path
)
if
attachment
.
original_filename
.
blank?
"must be set."
"must be set."
end
end
end
end
...
...
lib/paperclip/attachment.rb
View file @
f79dadce
...
@@ -15,7 +15,7 @@ module Paperclip
...
@@ -15,7 +15,7 @@ module Paperclip
}
}
end
end
attr_reader
:name
,
:instance
,
:
file
,
:
styles
,
:default_style
attr_reader
:name
,
:instance
,
:styles
,
:default_style
# Creates an Attachment object. +name+ is the name of the attachment, +instance+ is the
# Creates an Attachment object. +name+ is the name of the attachment, +instance+ is the
# ActiveRecord object instance it's attached to, and +options+ is the same as the hash
# ActiveRecord object instance it's attached to, and +options+ is the same as the hash
...
@@ -35,19 +35,13 @@ module Paperclip
...
@@ -35,19 +35,13 @@ module Paperclip
@storage
=
options
[
:storage
]
@storage
=
options
[
:storage
]
@options
=
options
@options
=
options
@queued_for_delete
=
[]
@queued_for_delete
=
[]
@
processed_files
=
{}
@
queued_for_write
=
{}
@errors
=
[]
@errors
=
[]
@file
=
nil
@validation_errors
=
nil
@validation_errors
=
nil
@dirty
=
false
@dirty
=
false
normalize_style_definition
normalize_style_definition
initialize_storage
initialize_storage
if
original_filename
@processed_files
=
locate_files
@file
=
@processed_files
[
@default_style
]
end
end
end
# What gets called when you call instance.attachment = File. It clears errors,
# What gets called when you call instance.attachment = File. It clears errors,
...
@@ -58,11 +52,11 @@ module Paperclip
...
@@ -58,11 +52,11 @@ module Paperclip
queue_existing_for_delete
queue_existing_for_delete
@errors
=
[]
@errors
=
[]
@validation_errors
=
nil
@validation_errors
=
nil
return
nil
if
uploaded_file
.
nil?
return
nil
if
uploaded_file
.
nil?
@
file
=
uploaded_file
.
to_tempfile
@
queued_for_write
[
:original
]
=
uploaded_file
.
to_tempfile
@instance
[
:"
#{
@name
}
_file_name"
]
=
uploaded_file
.
original_filename
@instance
[
:"
#{
@name
}
_file_name"
]
=
uploaded_file
.
original_filename
@instance
[
:"
#{
@name
}
_content_type"
]
=
uploaded_file
.
content_type
@instance
[
:"
#{
@name
}
_content_type"
]
=
uploaded_file
.
content_type
@instance
[
:"
#{
@name
}
_file_size"
]
=
uploaded_file
.
size
@instance
[
:"
#{
@name
}
_file_size"
]
=
uploaded_file
.
size
...
@@ -79,8 +73,8 @@ module Paperclip
...
@@ -79,8 +73,8 @@ module Paperclip
# and can point to an action in your app, if you need fine grained security.
# and can point to an action in your app, if you need fine grained security.
# This is not recommended if you don't need the security, however, for
# This is not recommended if you don't need the security, however, for
# performance reasons.
# performance reasons.
def
url
style
=
nil
def
url
style
=
default_style
@file
?
interpolate
(
@url
,
style
)
:
interpolate
(
@default_url
,
style
)
exists?
(
style
)
?
interpolate
(
@url
,
style
)
:
interpolate
(
@default_url
,
style
)
end
end
# Returns the path of the attachment as defined by the :path optionn. If the
# Returns the path of the attachment as defined by the :path optionn. If the
...
@@ -118,7 +112,6 @@ module Paperclip
...
@@ -118,7 +112,6 @@ module Paperclip
flush_deletes
flush_deletes
flush_writes
flush_writes
@dirty
=
false
@dirty
=
false
@file
=
@processed_files
[
default_style
]
true
true
else
else
flush_errors
flush_errors
...
@@ -126,14 +119,6 @@ module Paperclip
...
@@ -126,14 +119,6 @@ module Paperclip
end
end
end
end
# Returns representation of the data of the file assigned to the given
# style, in the format most representative of the current storage.
def
to_file
style
=
nil
@processed_files
[
style
||
default_style
]
end
alias_method
:to_io
,
:to_file
# Returns the name of the file as originally assigned, and as lives in the
# Returns the name of the file as originally assigned, and as lives in the
# <attachment>_file_name attribute of the model.
# <attachment>_file_name attribute of the model.
def
original_filename
def
original_filename
...
@@ -149,7 +134,7 @@ module Paperclip
...
@@ -149,7 +134,7 @@ module Paperclip
@interpolations
||=
{
@interpolations
||=
{
:rails_root
=>
lambda
{
|
attachment
,
style
|
RAILS_ROOT
},
:rails_root
=>
lambda
{
|
attachment
,
style
|
RAILS_ROOT
},
:class
=>
lambda
do
|
attachment
,
style
|
:class
=>
lambda
do
|
attachment
,
style
|
attachment
.
instance
.
class
.
to_s
.
downcas
e
.
pluralize
attachment
.
instance
.
class
.
name
.
underscor
e
.
pluralize
end
,
end
,
:basename
=>
lambda
do
|
attachment
,
style
|
:basename
=>
lambda
do
|
attachment
,
style
|
attachment
.
original_filename
.
gsub
(
/\.(.*?)$/
,
""
)
attachment
.
original_filename
.
gsub
(
/\.(.*?)$/
,
""
)
...
@@ -196,11 +181,11 @@ module Paperclip
...
@@ -196,11 +181,11 @@ module Paperclip
end
end
def
post_process
#:nodoc:
def
post_process
#:nodoc:
return
nil
if
@file
.
nil?
return
if
@queued_for_write
[
:original
]
.
nil?
@styles
.
each
do
|
name
,
args
|
@styles
.
each
do
|
name
,
args
|
begin
begin
dimensions
,
format
=
args
dimensions
,
format
=
args
@
processed_files
[
name
]
=
Thumbnail
.
make
(
self
.
file
,
@
queued_for_write
[
name
]
=
Thumbnail
.
make
(
@queued_for_write
[
:original
]
,
dimensions
,
dimensions
,
format
,
format
,
@whiny_thumnails
)
@whiny_thumnails
)
...
@@ -210,11 +195,9 @@ module Paperclip
...
@@ -210,11 +195,9 @@ module Paperclip
@errors
<<
e
.
message
@errors
<<
e
.
message
end
end
end
end
@processed_files
[
:original
]
=
@file
end
end
def
interpolate
pattern
,
style
=
nil
#:nodoc:
def
interpolate
pattern
,
style
=
default_style
#:nodoc:
style
||=
default_style
pattern
=
pattern
.
dup
pattern
=
pattern
.
dup
self
.
class
.
interpolations
.
each
do
|
tag
,
l
|
self
.
class
.
interpolations
.
each
do
|
tag
,
l
|
pattern
.
gsub!
(
/:\b
#{
tag
}
\b/
)
do
|
match
|
pattern
.
gsub!
(
/:\b
#{
tag
}
\b/
)
do
|
match
|
...
@@ -225,9 +208,10 @@ module Paperclip
...
@@ -225,9 +208,10 @@ module Paperclip
end
end
def
queue_existing_for_delete
#:nodoc:
def
queue_existing_for_delete
#:nodoc:
@queued_for_delete
+=
@processed_files
.
values
return
if
original_filename
.
blank?
@file
=
nil
@queued_for_delete
+=
[
:original
,
*
@styles
.
keys
].
uniq
.
map
do
|
style
|
@processed_files
=
{}
path
(
style
)
if
exists?
(
style
)
end
.
compact
@instance
[
:"
#{
@name
}
_file_name"
]
=
nil
@instance
[
:"
#{
@name
}
_file_name"
]
=
nil
@instance
[
:"
#{
@name
}
_content_type"
]
=
nil
@instance
[
:"
#{
@name
}
_content_type"
]
=
nil
@instance
[
:"
#{
@name
}
_file_size"
]
=
nil
@instance
[
:"
#{
@name
}
_file_size"
]
=
nil
...
...
lib/paperclip/iostream.rb
View file @
f79dadce
...
@@ -25,7 +25,7 @@ module IOStream
...
@@ -25,7 +25,7 @@ module IOStream
while
self
.
read
(
in_blocks_of
,
buffer
)
do
while
self
.
read
(
in_blocks_of
,
buffer
)
do
dstio
.
write
(
buffer
)
dstio
.
write
(
buffer
)
end
end
dstio
.
rewind
dstio
.
rewind
dstio
dstio
end
end
end
end
...
...
lib/paperclip/storage.rb
View file @
f79dadce
module
Paperclip
module
Paperclip
module
Storage
module
Storage
# With the Filesystem module installed, @file and @processed_files are just File instances.
module
Filesystem
module
Filesystem
def
self
.
extended
base
def
self
.
extended
base
end
end
def
locate_files
def
exists?
(
style
=
default_style
)
[
:original
,
*
@styles
.
keys
].
uniq
.
inject
({})
do
|
files
,
style
|
if
original_filename
files
[
style
]
=
File
.
new
(
path
(
style
),
"rb"
)
if
File
.
exist?
(
path
(
style
))
File
.
exist?
(
path
(
style
))
files
else
false
end
end
end
end
# Returns representation of the data of the file assigned to the given
# style, in the format most representative of the current storage.
def
to_file
style
=
default_style
File
.
new
(
path
(
style
))
if
exists?
(
style
)
end
alias_method
:to_io
,
:to_file
def
flush_writes
#:nodoc:
def
flush_writes
#:nodoc:
@processed_files
.
each
do
|
style
,
file
|
@queued_for_write
.
each
do
|
style
,
file
|
FileUtils
.
mkdir_p
(
File
.
dirname
(
path
(
style
))
)
FileUtils
.
mkdir_p
(
File
.
dirname
(
path
(
style
)))
@processed_files
[
style
]
=
file
.
stream_to
(
path
(
style
))
unless
file
.
path
==
path
(
style
)
result
=
file
.
stream_to
(
path
(
style
))
file
.
close
result
.
close
end
end
@queued_for_write
=
{}
end
end
def
flush_deletes
#:nodoc:
def
flush_deletes
#:nodoc:
@queued_for_delete
.
compact
.
each
do
|
file
|
@queued_for_delete
.
each
do
|
path
|
begin
begin
FileUtils
.
rm
(
file
.
path
)
FileUtils
.
rm
(
path
)
if
File
.
exist?
(
path
)
rescue
Errno
::
ENOENT
=>
e
rescue
Errno
::
ENOENT
=>
e
# ignore them
# ignore them
end
end
...
@@ -32,8 +42,6 @@ module Paperclip
...
@@ -32,8 +42,6 @@ module Paperclip
end
end
end
end
# With the S3 module included, @file and the @processed_files will be
# RightAws::S3::Key instances.
module
S3
module
S3
def
self
.
extended
base
def
self
.
extended
base
require
'right_aws'
require
'right_aws'
...
@@ -58,35 +66,37 @@ module Paperclip
...
@@ -58,35 +66,37 @@ module Paperclip
creds
=
find_credentials
(
creds
).
stringify_keys
creds
=
find_credentials
(
creds
).
stringify_keys
(
creds
[
ENV
[
'RAILS_ENV'
]]
||
creds
).
symbolize_keys
(
creds
[
ENV
[
'RAILS_ENV'
]]
||
creds
).
symbolize_keys
end
end
def
exists?
(
style
=
default_style
)
@s3_bucket
.
key
(
path
(
style
))
?
true
:
false
end
def
locate_files
# Returns representation of the data of the file assigned to the given
[
:original
,
*
@styles
.
keys
].
uniq
.
inject
({})
do
|
files
,
style
|
# style, in the format most representative of the current storage.
files
[
style
]
=
@s3_bucket
.
key
(
path
(
style
))
def
to_file
style
=
default_style
files
@s3_bucket
.
key
(
path
(
style
))
end
end
end
alias_method
:to_io
,
:to_file
def
flush_writes
#:nodoc:
def
flush_writes
#:nodoc:
return
if
not
dirty?
@queued_for_write
.
each
do
|
style
,
file
|
@processed_files
.
each
do
|
style
,
key
|
begin
begin
unless
key
.
is_a?
RightAws
::
S3
::
Key
key
=
@s3_bucket
.
key
(
path
(
style
))
saved_data
=
key
key
.
data
=
file
key
=
@processed_files
[
style
]
=
@s3_bucket
.
key
(
path
(
style
))
key
.
data
=
saved_data
end
key
.
put
(
nil
,
@s3_permissions
)
key
.
put
(
nil
,
@s3_permissions
)
rescue
RightAws
::
AwsError
=>
e
rescue
RightAws
::
AwsError
=>
e
@processed_files
[
style
]
=
nil
raise
raise
end
end
end
end
@queued_for_write
=
{}
end
end
def
flush_deletes
#:nodoc:
def
flush_deletes
#:nodoc:
@queued_for_delete
.
compact
.
each
do
|
file
|
@queued_for_delete
.
each
do
|
path
|
begin
begin
file
.
delete
if
file
=
@s3_bucket
.
key
(
path
)
file
.
delete
end
rescue
RightAws
::
AwsError
rescue
RightAws
::
AwsError
# Ignore this.
# Ignore this.
end
end
...
...
test/test_attachment.rb
View file @
f79dadce
...
@@ -28,6 +28,16 @@ class AttachmentTest < Test::Unit::TestCase
...
@@ -28,6 +28,16 @@ class AttachmentTest < Test::Unit::TestCase
end
end
end
end
context
"without an Attachment"
do
setup
do
@dummy
=
Dummy
.
new
end
should
"return false when asked exists?"
do
assert
!
@dummy
.
avatar
.
exists?
end
end
context
"on an Attachment"
do
context
"on an Attachment"
do
setup
do
setup
do
@dummy
=
Dummy
.
new
@dummy
=
Dummy
.
new
...
@@ -96,7 +106,7 @@ class AttachmentTest < Test::Unit::TestCase
...
@@ -96,7 +106,7 @@ class AttachmentTest < Test::Unit::TestCase
end
end
should
"return its default_url when no file assigned"
do
should
"return its default_url when no file assigned"
do
assert
@attachment
.
file
.
nil?
assert
@attachment
.
to_
file
.
nil?
assert_equal
"/tests/original/missing.png"
,
@attachment
.
url
assert_equal
"/tests/original/missing.png"
,
@attachment
.
url
assert_equal
"/tests/blah/missing.png"
,
@attachment
.
url
(
:blah
)
assert_equal
"/tests/blah/missing.png"
,
@attachment
.
url
(
:blah
)
end
end
...
@@ -123,29 +133,28 @@ class AttachmentTest < Test::Unit::TestCase
...
@@ -123,29 +133,28 @@ class AttachmentTest < Test::Unit::TestCase
@attachment
.
assign
(
@file
)
@attachment
.
assign
(
@file
)
end
end
should
"return the real url"
do
assert
@attachment
.
file
assert_equal
"/tests/41/original/5k.png"
,
@attachment
.
url
assert_equal
"/tests/41/blah/5k.png"
,
@attachment
.
url
(
:blah
)
end
should
"be dirty"
do
should
"be dirty"
do
assert
@attachment
.
dirty?
assert
@attachment
.
dirty?
end
end
should
"have its image and attachments as tempfiles"
do
[
nil
,
:large
,
:medium
,
:small
].
each
do
|
style
|
assert
File
.
exists?
(
@attachment
.
to_io
(
style
))
end
end
context
"and saved"
do
context
"and saved"
do
setup
do
setup
do
@attachment
.
save
@attachment
.
save
end
end
should
"return the real url"
do
assert
@attachment
.
to_file
assert_equal
"/tests/41/original/5k.png"
,
@attachment
.
url
assert_equal
"/tests/41/small/5k.jpg"
,
@attachment
.
url
(
:small
)
end
should
"return its default_url when no file assigned"
do
assert
@attachment
.
to_file
assert_equal
"/tests/blah/missing.png"
,
@attachment
.
url
(
:blah
)
end
should
"commit the files to disk"
do
should
"commit the files to disk"
do
[
nil
,
:large
,
:medium
,
:small
].
each
do
|
style
|
[
:large
,
:medium
,
:small
].
each
do
|
style
|
io
=
@attachment
.
to_io
(
style
)
io
=
@attachment
.
to_io
(
style
)
assert
File
.
exists?
(
io
)
assert
File
.
exists?
(
io
)
assert
!
io
.
is_a?
(
::
Tempfile
)
assert
!
io
.
is_a?
(
::
Tempfile
)
...
@@ -166,12 +175,25 @@ class AttachmentTest < Test::Unit::TestCase
...
@@ -166,12 +175,25 @@ class AttachmentTest < Test::Unit::TestCase
end
end
end
end
should
"
have #file be equal #to_io(:original)
"
do
should
"
still have its #file attribute not be nil
"
do
assert
_equal
@attachment
.
file
,
@attachment
.
to_io
(
:original
)
assert
!
@attachment
.
to_file
.
nil?
end
end
should
"still have its #file attribute not be nil"
do
context
"and deleted"
do
assert
!
@attachment
.
file
.
nil?
setup
do
@existing_names
=
@attachment
.
styles
.
keys
.
collect
do
|
style
|
@attachment
.
path
(
style
)
end
@instance
.
expects
(
:[]=
).
with
(
:test_file_name
,
nil
)
@instance
.
expects
(
:[]=
).
with
(
:test_content_type
,
nil
)
@instance
.
expects
(
:[]=
).
with
(
:test_file_size
,
nil
)
@attachment
.
assign
nil
@attachment
.
save
end
should
"delete the files"
do
@existing_names
.
each
{
|
f
|
assert
!
File
.
exists?
(
f
)
}
end
end
end
context
"and deleted"
do
context
"and deleted"
do
...
...
test/test_integration.rb
View file @
f79dadce
require
'test/helper.rb'
require
'test/helper.rb'
class
IntegrationTest
<
Test
::
Unit
::
TestCase
class
IntegrationTest
<
Test
::
Unit
::
TestCase
context
"Many models at once"
do
setup
do
rebuild_model
@file
=
File
.
new
(
File
.
join
(
FIXTURES_DIR
,
"5k.png"
))
300
.
times
do
|
i
|
Dummy
.
create!
:avatar
=>
@file
end
end
should
"not exceed the open file limit"
do
assert_nothing_raised
do
dummies
=
Dummy
.
find
(
:all
)
dummies
.
each
{
|
dummy
|
dummy
.
avatar
}
end
end
end
context
"A model with a filesystem attachment"
do
context
"A model with a filesystem attachment"
do
setup
do
setup
do
rebuild_model
:styles
=>
{
:large
=>
"300x300>"
,
rebuild_model
:styles
=>
{
:large
=>
"300x300>"
,
...
@@ -19,8 +36,7 @@ class IntegrationTest < Test::Unit::TestCase
...
@@ -19,8 +36,7 @@ class IntegrationTest < Test::Unit::TestCase
end
end
should
"write and delete its files"
do
should
"write and delete its files"
do
[[
"100x15"
,
nil
],
[[
"434x66"
,
:original
],
[
"434x66"
,
:original
],
[
"300x46"
,
:large
],
[
"300x46"
,
:large
],
[
"100x15"
,
:medium
],
[
"100x15"
,
:medium
],
[
"32x32"
,
:thumb
]].
each
do
|
geo
,
style
|
[
"32x32"
,
:thumb
]].
each
do
|
geo
,
style
|
...
@@ -78,10 +94,10 @@ class IntegrationTest < Test::Unit::TestCase
...
@@ -78,10 +94,10 @@ class IntegrationTest < Test::Unit::TestCase
end
end
should
"know the difference between good files, bad files, not files, and nil"
do
should
"know the difference between good files, bad files, not files, and nil"
do
expected
=
@dummy
.
avatar
.
file
expected
=
@dummy
.
avatar
.
to_
file
@dummy
.
avatar
=
"not a file"
@dummy
.
avatar
=
"not a file"
assert
@dummy
.
valid?
assert
@dummy
.
valid?
assert_equal
expected
.
path
,
@dummy
.
avatar
.
file
.
path
assert_equal
expected
.
path
,
@dummy
.
avatar
.
to_
file
.
path
@dummy
.
avatar
=
@bad_file
@dummy
.
avatar
=
@bad_file
assert
!
@dummy
.
valid?
assert
!
@dummy
.
valid?
...
@@ -204,10 +220,10 @@ class IntegrationTest < Test::Unit::TestCase
...
@@ -204,10 +220,10 @@ class IntegrationTest < Test::Unit::TestCase
end
end
should
"know the difference between good files, bad files, not files, and nil"
do
should
"know the difference between good files, bad files, not files, and nil"
do
expected
=
@dummy
.
avatar
.
file
expected
=
@dummy
.
avatar
.
to_
file
@dummy
.
avatar
=
"not a file"
@dummy
.
avatar
=
"not a file"
assert
@dummy
.
valid?
assert
@dummy
.
valid?
assert_equal
expected
,
@dummy
.
avatar
.
file
assert_equal
expected
,
@dummy
.
avatar
.
to_
file
@dummy
.
avatar
=
@bad_file
@dummy
.
avatar
=
@bad_file
assert
!
@dummy
.
valid?
assert
!
@dummy
.
valid?
...
...
test/test_storage.rb
View file @
f79dadce
...
@@ -78,10 +78,6 @@ class S3Test < Test::Unit::TestCase
...
@@ -78,10 +78,6 @@ class S3Test < Test::Unit::TestCase
@dummy
.
avatar
=
@file
@dummy
.
avatar
=
@file
end
end
should
"still return a Tempfile when sent #to_io"
do
assert_equal
Tempfile
,
@dummy
.
avatar
.
to_io
.
class
end
context
"and saved"
do
context
"and saved"
do
setup
do
setup
do
@key_mock
=
stub
@key_mock
=
stub
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment