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
f8fff43d
Commit
f8fff43d
authored
Aug 01, 2008
by
Henrik N
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'tb/master'
parents
27727359
e483854d
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
162 additions
and
47 deletions
+162
-47
Rakefile
+5
-1
generators/paperclip/USAGE
+2
-1
lib/paperclip.rb
+13
-3
lib/paperclip/attachment.rb
+26
-6
lib/paperclip/geometry.rb
+1
-1
lib/paperclip/storage.rb
+10
-1
lib/paperclip/upfile.rb
+9
-5
tasks/paperclip_tasks.rake
+55
-14
test/attachment_test.rb
+1
-0
test/geometry_test.rb
+0
-0
test/integration_test.rb
+0
-0
test/iostream_test.rb
+0
-0
test/paperclip_test.rb
+40
-15
test/storage_test.rb
+0
-0
test/thumbnail_test.rb
+0
-0
No files found.
Rakefile
View file @
f8fff43d
...
...
@@ -12,7 +12,7 @@ task :default => [:clean, :test]
desc
'Test the paperclip plugin.'
Rake
::
TestTask
.
new
(
:test
)
do
|
t
|
t
.
libs
<<
'lib'
<<
'profile'
t
.
pattern
=
'test/**/
test_*
.rb'
t
.
pattern
=
'test/**/
*_test
.rb'
t
.
verbose
=
true
end
...
...
@@ -46,6 +46,7 @@ task :clean do |t|
end
spec
=
Gem
::
Specification
.
new
do
|
s
|
s
.
rubygems_version
=
"1.2.0"
s
.
name
=
"paperclip"
s
.
version
=
Paperclip
::
VERSION
s
.
author
=
"Jon Yurek"
...
...
@@ -65,6 +66,9 @@ spec = Gem::Specification.new do |s|
s
.
extra_rdoc_files
=
[
"README"
]
s
.
rdoc_options
<<
'--line-numbers'
<<
'--inline-source'
s
.
requirements
<<
"ImageMagick"
s
.
add_runtime_dependency
'right_aws'
s
.
add_development_dependency
'Shoulda'
s
.
add_development_dependency
'mocha'
end
Rake
::
GemPackageTask
.
new
(
spec
)
do
|
pkg
|
...
...
generators/paperclip/USAGE
View file @
f8fff43d
Usage:
script/generate
attachment Class attachment1 attachment2
script/generate
paperclip Class attachment1 (attachment2 ...)
This will create a migration that will add the proper columns to your class's table.
\ No newline at end of file
lib/paperclip.rb
View file @
f8fff43d
...
...
@@ -113,6 +113,12 @@ module Paperclip
def
has_attached_file
name
,
options
=
{}
include
InstanceMethods
%w(file_name content_type)
.
each
do
|
field
|
unless
column_names
.
include?
(
"
#{
name
}
_
#{
field
}
"
)
raise
PaperclipError
.
new
(
"
#{
self
}
model does not have required column '
#{
name
}
_
#{
field
}
'"
)
end
end
write_inheritable_attribute
(
:attachment_definitions
,
{})
if
attachment_definitions
.
nil?
attachment_definitions
[
name
]
=
{
:validations
=>
[]}.
merge
(
options
)
...
...
@@ -133,7 +139,7 @@ module Paperclip
end
validates_each
(
name
)
do
|
record
,
attr
,
value
|
value
.
send
(
:flush_errors
)
value
.
send
(
:flush_errors
)
unless
value
.
valid?
end
end
...
...
@@ -180,7 +186,11 @@ module Paperclip
# Places ActiveRecord-style validations on the content type of the file assigned. The
# possible options are:
# * +content_type+: Allowed content types. Can be a single content type or an array. Allows all by default.
# * +content_type+: Allowed content types. Can be a single content type or an array.
# Each type can be a String or a Regexp. It should be noted that Internet Explorer uploads
# files with content_types that you may not expect. For example, JPEG images are given
# image/pjpeg and PNGs are image/x-png, so keep that in mind when determining how you match.
# Allows all by default.
# * +message+: The message to display when the uploaded file has an invalid content type.
def
validates_attachment_content_type
name
,
options
=
{}
attachment_definitions
[
name
][
:validations
]
<<
lambda
do
|
attachment
,
instance
|
...
...
@@ -190,7 +200,7 @@ module Paperclip
unless
options
[
:content_type
].
blank?
content_type
=
instance
[
:"
#{
name
}
_content_type"
]
unless
valid_types
.
any?
{
|
t
|
t
===
content_type
}
options
[
:message
]
||
ActiveRecord
::
Errors
.
default_error_messages
[
:inclusion
]
options
[
:message
]
||
"is not one of the allowed file types."
end
end
end
...
...
lib/paperclip/attachment.rb
View file @
f8fff43d
...
...
@@ -43,6 +43,8 @@ module Paperclip
normalize_style_definition
initialize_storage
logger
.
info
(
"[paperclip] Paperclip attachment
#{
name
}
on
#{
instance
.
class
}
initialized."
)
end
# What gets called when you call instance.attachment = File. It clears errors,
...
...
@@ -50,6 +52,7 @@ module Paperclip
# the previous file for deletion, to be flushed away on #save of its host.
def
assign
uploaded_file
return
nil
unless
valid_assignment?
(
uploaded_file
)
logger
.
info
(
"[paperclip] Assigning
#{
uploaded_file
}
to
#{
name
}
"
)
queue_existing_for_delete
@errors
=
[]
...
...
@@ -57,6 +60,7 @@ module Paperclip
return
nil
if
uploaded_file
.
nil?
logger
.
info
(
"[paperclip] Writing attributes for
#{
name
}
"
)
@queued_for_write
[
:original
]
=
uploaded_file
.
to_tempfile
@instance
[
:"
#{
@name
}
_file_name"
]
=
uploaded_file
.
original_filename
.
strip
.
gsub
/[^\w\d\.\-]+/
,
'_'
@instance
[
:"
#{
@name
}
_content_type"
]
=
uploaded_file
.
content_type
.
strip
...
...
@@ -95,6 +99,7 @@ module Paperclip
# Returns true if there are any errors on this attachment.
def
valid?
validate
errors
.
length
==
0
end
...
...
@@ -112,11 +117,13 @@ module Paperclip
# the instance's errors and returns false, cancelling the save.
def
save
if
valid?
logger
.
info
(
"[paperclip] Saving files for
#{
name
}
"
)
flush_deletes
flush_writes
@dirty
=
false
true
else
logger
.
info
(
"[paperclip] Errors on
#{
name
}
. Not saving."
)
flush_errors
false
end
...
...
@@ -166,18 +173,27 @@ module Paperclip
# again.
def
reprocess!
new_original
=
Tempfile
.
new
(
"paperclip-reprocess"
)
old_original
=
to_file
(
:original
)
new_original
.
write
(
old_original
.
read
)
new_original
.
rewind
if
old_original
=
to_file
(
:original
)
new_original
.
write
(
old_original
.
read
)
new_original
.
rewind
@queued_for_write
=
{
:original
=>
new_original
}
post_process
@queued_for_write
=
{
:original
=>
new_original
}
post_process
old_original
.
close
if
old_original
.
respond_to?
(
:close
)
old_original
.
close
if
old_original
.
respond_to?
(
:close
)
save
else
true
end
end
private
def
logger
instance
.
logger
end
def
valid_assignment?
file
#:nodoc:
file
.
nil?
||
(
file
.
respond_to?
(
:original_filename
)
&&
file
.
respond_to?
(
:content_type
))
end
...
...
@@ -189,6 +205,7 @@ module Paperclip
end
.
flatten
.
compact
.
uniq
@errors
+=
@validation_errors
end
@validation_errors
end
def
normalize_style_definition
...
...
@@ -206,9 +223,11 @@ module Paperclip
def
post_process
#:nodoc:
return
if
@queued_for_write
[
:original
].
nil?
logger
.
info
(
"[paperclip] Post-processing
#{
name
}
"
)
@styles
.
each
do
|
name
,
args
|
begin
dimensions
,
format
=
args
dimensions
=
dimensions
.
call
(
instance
)
if
dimensions
.
respond_to?
:call
@queued_for_write
[
name
]
=
Thumbnail
.
make
(
@queued_for_write
[
:original
],
dimensions
,
format
,
...
...
@@ -231,6 +250,7 @@ module Paperclip
def
queue_existing_for_delete
#:nodoc:
return
if
original_filename
.
blank?
logger
.
info
(
"[paperclip] Queueing the existing files for
#{
name
}
for deletion."
)
@queued_for_delete
+=
[
:original
,
*
@styles
.
keys
].
uniq
.
map
do
|
style
|
path
(
style
)
if
exists?
(
style
)
end
.
compact
...
...
lib/paperclip/geometry.rb
View file @
f8fff43d
...
...
@@ -76,9 +76,9 @@ module Paperclip
# overhanging image would be cropped. Useful for square thumbnail images. The cropping
# is weighted at the center of the Geometry.
def
transformation_to
dst
,
crop
=
false
ratio
=
Geometry
.
new
(
dst
.
width
/
self
.
width
,
dst
.
height
/
self
.
height
)
if
crop
ratio
=
Geometry
.
new
(
dst
.
width
/
self
.
width
,
dst
.
height
/
self
.
height
)
scale_geometry
,
scale
=
scaling
(
dst
,
ratio
)
crop_geometry
=
cropping
(
dst
,
ratio
,
scale
)
else
...
...
lib/paperclip/storage.rb
View file @
f8fff43d
...
...
@@ -9,7 +9,7 @@ module Paperclip
# almost all cases, should) be coordinated with the value of the +url+ option to
# allow files to be saved into a place where Apache can serve them without
# hitting your app. Defaults to
# ":rails_root/public/:
class/:attachment/:id/:style_:filename".
# ":rails_root/public/:
attachment/:id/:style/:basename.:extension"
# By default this places the files in the app's public directory which can be served
# directly. If you are using capistrano for deployment, a good idea would be to
# make a symlink to the capistrano-created system directory from inside your app's
...
...
@@ -36,8 +36,10 @@ module Paperclip
alias_method
:to_io
,
:to_file
def
flush_writes
#:nodoc:
logger
.
info
(
"[paperclip] Writing files for
#{
name
}
"
)
@queued_for_write
.
each
do
|
style
,
file
|
FileUtils
.
mkdir_p
(
File
.
dirname
(
path
(
style
)))
logger
.
info
(
"[paperclip] ->
#{
path
(
style
)
}
"
)
result
=
file
.
stream_to
(
path
(
style
))
file
.
close
result
.
close
...
...
@@ -46,8 +48,10 @@ module Paperclip
end
def
flush_deletes
#:nodoc:
logger
.
info
(
"[paperclip] Deleting files for
#{
name
}
"
)
@queued_for_delete
.
each
do
|
path
|
begin
logger
.
info
(
"[paperclip] ->
#{
path
}
"
)
FileUtils
.
rm
(
path
)
if
File
.
exist?
(
path
)
rescue
Errno
::
ENOENT
=>
e
# ignore file-not-found, let everything else pass
...
...
@@ -102,6 +106,7 @@ module Paperclip
base
.
class
.
interpolations
[
:s3_url
]
=
lambda
do
|
attachment
,
style
|
"https://s3.amazonaws.com/
#{
attachment
.
bucket_name
}
/
#{
attachment
.
path
(
style
).
gsub
(
%r{^/}
,
""
)
}
"
end
ActiveRecord
::
Base
.
logger
.
info
(
"[paperclip] S3 Storage Initalized."
)
end
def
s3
...
...
@@ -135,8 +140,10 @@ module Paperclip
alias_method
:to_io
,
:to_file
def
flush_writes
#:nodoc:
logger
.
info
(
"[paperclip] Writing files for
#{
name
}
"
)
@queued_for_write
.
each
do
|
style
,
file
|
begin
logger
.
info
(
"[paperclip] ->
#{
path
(
style
)
}
"
)
key
=
s3_bucket
.
key
(
path
(
style
))
key
.
data
=
file
key
.
put
(
nil
,
@s3_permissions
)
...
...
@@ -148,8 +155,10 @@ module Paperclip
end
def
flush_deletes
#:nodoc:
logger
.
info
(
"[paperclip] Writing files for
#{
name
}
"
)
@queued_for_delete
.
each
do
|
path
|
begin
logger
.
info
(
"[paperclip] ->
#{
path
(
style
)
}
"
)
if
file
=
s3_bucket
.
key
(
path
)
file
.
delete
end
...
...
lib/paperclip/upfile.rb
View file @
f8fff43d
...
...
@@ -6,12 +6,15 @@ module Paperclip
# Infer the MIME-type of the file from the extension.
def
content_type
type
=
self
.
path
.
match
(
/\.(\w+)$/
)[
1
]
rescue
"octet-stream"
type
=
(
self
.
path
.
match
(
/\.(\w+)$/
)[
1
]
rescue
"octet-stream"
).
downcase
case
type
when
"jpg"
,
"png"
,
"gif"
then
"image/
#{
type
}
"
when
"txt"
then
"text/plain"
when
"csv"
,
"xml"
,
"html"
,
"htm"
,
"css"
,
"js"
then
"text/
#{
type
}
"
else
"x-application/
#{
type
}
"
when
%r"jpe?g"
then
"image/jpeg"
when
%r"tiff?"
then
"image/tiff"
when
%r"png"
,
"gif"
,
"bmp"
then
"image/
#{
type
}
"
when
"txt"
then
"text/plain"
when
%r"html?"
then
"text/html"
when
"csv"
,
"xml"
,
"css"
,
"js"
then
"text/
#{
type
}
"
else
"application/x-
#{
type
}
"
end
end
...
...
@@ -31,3 +34,4 @@ end
class
File
#:nodoc:
include
Paperclip
::
Upfile
end
tasks/paperclip_tasks.rake
View file @
f8fff43d
...
...
@@ -14,25 +14,66 @@ def obtain_attachments
end
end
def
for_all_attachments
klass
=
obtain_class
names
=
obtain_attachments
ids
=
klass
.
connection
.
select_values
(
"SELECT id FROM
#{
klass
.
table_name
}
"
)
ids
.
each
do
|
id
|
instance
=
klass
.
find
(
id
)
names
.
each
do
|
name
|
result
=
if
instance
.
send
(
"
#{
name
}
?"
)
yield
(
instance
,
name
)
else
true
end
print
result
?
"."
:
"x"
;
$stdout
.
flush
end
end
puts
" Done."
end
namespace
:paperclip
do
desc
"Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)"
task
:refresh
=>
:environment
do
klass
=
obtain_class
names
=
obtain_attachments
instances
=
klass
.
find
(
:all
)
puts
"Regenerating thumbnails for
#{
instances
.
length
}
instances of
#{
klass
.
name
}
:"
instances
.
each
do
|
instance
|
names
.
each
do
|
name
|
result
=
if
instance
.
send
(
"
#{
name
}
?"
)
instance
.
send
(
name
).
reprocess!
instance
.
send
(
name
).
save
desc
"Refreshes both metadata and thumbnails."
task
:refresh
=>
[
"paperclip:refresh:metadata"
,
"paperclip:refresh:thumbnails"
]
namespace
:refresh
do
desc
"Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)."
task
:thumbnails
=>
:environment
do
errors
=
[]
for_all_attachments
do
|
instance
,
name
|
result
=
instance
.
send
(
name
).
reprocess!
errors
<<
[
instance
.
id
,
instance
.
errors
]
unless
instance
.
errors
.
blank?
result
end
errors
.
each
{
|
e
|
puts
"
#{
e
.
first
}
:
#{
e
.
last
.
full_messages
.
inspect
}
"
}
end
desc
"Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT)."
task
:metadata
=>
:environment
do
for_all_attachments
do
|
instance
,
name
|
if
file
=
instance
.
send
(
name
).
to_file
instance
.
send
(
"
#{
name
}
_file_name="
,
instance
.
send
(
"
#{
name
}
_file_name"
).
strip
)
instance
.
send
(
"
#{
name
}
_content_type="
,
file
.
content_type
.
strip
)
instance
.
send
(
"
#{
name
}
_file_size="
,
file
.
size
)
if
instance
.
respond_to?
(
"
#{
name
}
_file_size"
)
instance
.
save
(
false
)
else
true
end
print
result
?
"."
:
"x"
;
$stdout
.
flush
end
end
puts
" Done."
end
desc
"Cleans out invalid attachments. Useful after you've added new validations."
task
:clean
=>
:environment
do
for_all_attachments
do
|
instance
,
name
|
instance
.
send
(
name
).
send
(
:validate
)
if
instance
.
send
(
name
).
valid?
true
else
instance
.
send
(
"
#{
name
}
="
,
nil
)
instance
.
save
end
end
end
end
test/
test_attachmen
t.rb
→
test/
attachment_tes
t.rb
View file @
f8fff43d
...
...
@@ -155,6 +155,7 @@ class AttachmentTest < Test::Unit::TestCase
@instance
.
stubs
(
:[]
).
with
(
:test_content_type
).
returns
(
nil
)
@instance
.
stubs
(
:[]
).
with
(
:test_file_size
).
returns
(
nil
)
@instance
.
stubs
(
:[]
).
with
(
:test_updated_at
).
returns
(
nil
)
@instance
.
stubs
(
:logger
).
returns
(
ActiveRecord
::
Base
.
logger
)
@attachment
=
Paperclip
::
Attachment
.
new
(
:test
,
@instance
)
@file
=
File
.
new
(
File
.
join
(
File
.
dirname
(
__FILE__
),
...
...
test/
test_geometry
.rb
→
test/
geometry_test
.rb
View file @
f8fff43d
File moved
test/
test_integration
.rb
→
test/
integration_test
.rb
View file @
f8fff43d
File moved
test/
test_iostream
.rb
→
test/
iostream_test
.rb
View file @
f8fff43d
File moved
test/
test_paperclip
.rb
→
test/
paperclip_test
.rb
View file @
f8fff43d
...
...
@@ -7,6 +7,14 @@ class PaperclipTest < Test::Unit::TestCase
@file
=
File
.
new
(
File
.
join
(
FIXTURES_DIR
,
"5k.png"
))
end
should
"error when trying to also create a 'blah' attachment"
do
assert_raises
(
Paperclip
::
PaperclipError
)
do
Dummy
.
class_eval
do
has_attached_file
:blah
end
end
end
context
"that is attr_protected"
do
setup
do
Dummy
.
class_eval
do
...
...
@@ -64,6 +72,38 @@ class PaperclipTest < Test::Unit::TestCase
assert
Dummy
.
new
.
respond_to?
(
:avatar
=
)
end
context
"that is valid"
do
setup
do
@dummy
=
Dummy
.
new
@dummy
.
avatar
=
@file
end
should
"be valid"
do
assert
@dummy
.
valid?
end
context
"then has a validation added that makes it invalid"
do
setup
do
assert
@dummy
.
save
Dummy
.
class_eval
do
validates_attachment_content_type
:avatar
,
:content_type
=>
[
"text/plain"
]
end
@dummy2
=
Dummy
.
find
(
@dummy
.
id
)
end
should
"be invalid when reloaded"
do
assert
!
@dummy2
.
valid?
,
@dummy2
.
errors
.
inspect
end
should
"be able to call #valid? twice without having duplicate errors"
do
@dummy2
.
avatar
.
valid?
first_errors
=
@dummy2
.
avatar
.
errors
@dummy2
.
avatar
.
valid?
assert_equal
first_errors
,
@dummy2
.
avatar
.
errors
end
end
end
[[
:presence
,
nil
,
"5k.png"
,
nil
],
[
:size
,
{
:in
=>
1
..
10240
},
"5k.png"
,
"12k.png"
],
[
:size2
,
{
:in
=>
1
..
10240
},
nil
,
"12k.png"
],
...
...
@@ -102,21 +142,6 @@ class PaperclipTest < Test::Unit::TestCase
assert_equal
1
,
@dummy
.
avatar
.
errors
.
length
end
end
# context "and an invalid file with :message" do
# setup do
# @file = args[3] && File.new(File.join(FIXTURES_DIR, args[3]))
# end
#
# should "have errors" do
# if args[1] && args[1][:message] && args[4]
# @dummy.avatar = @file
# assert ! @dummy.avatar.valid?
# assert_equal 1, @dummy.avatar.errors.length
# assert_equal args[4], @dummy.avatar.errors[0]
# end
# end
# end
end
end
end
...
...
test/
test_storage
.rb
→
test/
storage_test
.rb
View file @
f8fff43d
File moved
test/t
est_thumbnail
.rb
→
test/t
humbnail_test
.rb
View file @
f8fff43d
File moved
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