betelgeuse-paperclip 2.2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +26 -0
- data/README.rdoc +172 -0
- data/Rakefile +77 -0
- data/generators/paperclip/USAGE +5 -0
- data/generators/paperclip/paperclip_generator.rb +27 -0
- data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
- data/init.rb +1 -0
- data/lib/paperclip.rb +351 -0
- data/lib/paperclip/attachment.rb +404 -0
- data/lib/paperclip/callback_compatability.rb +33 -0
- data/lib/paperclip/geometry.rb +115 -0
- data/lib/paperclip/iostream.rb +58 -0
- data/lib/paperclip/matchers.rb +4 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +49 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +66 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +48 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +83 -0
- data/lib/paperclip/processor.rb +48 -0
- data/lib/paperclip/storage.rb +432 -0
- data/lib/paperclip/thumbnail.rb +70 -0
- data/lib/paperclip/upfile.rb +48 -0
- data/shoulda_macros/paperclip.rb +68 -0
- data/tasks/paperclip_tasks.rake +79 -0
- metadata +109 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# Handles thumbnailing images that are uploaded.
|
3
|
+
class Thumbnail < Processor
|
4
|
+
|
5
|
+
attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options
|
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+ is true (which it is, by default. If +convert_options+ is
|
12
|
+
# set, the options will be appended to the convert command upon image conversion
|
13
|
+
def initialize file, options = {}, attachment = nil
|
14
|
+
super
|
15
|
+
geometry = options[:geometry]
|
16
|
+
@file = file
|
17
|
+
@crop = geometry[-1,1] == '#'
|
18
|
+
@target_geometry = Geometry.parse geometry
|
19
|
+
@current_geometry = Geometry.from_file @file
|
20
|
+
@convert_options = options[:convert_options]
|
21
|
+
@whiny = options[:whiny].nil? ? true : options[:whiny]
|
22
|
+
@format = options[:format]
|
23
|
+
|
24
|
+
@current_format = File.extname(@file.path)
|
25
|
+
@basename = File.basename(@file.path, @current_format)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns true if the +target_geometry+ is meant to crop.
|
29
|
+
def crop?
|
30
|
+
@crop
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns true if the image is meant to make use of additional convert options.
|
34
|
+
def convert_options?
|
35
|
+
not @convert_options.blank?
|
36
|
+
end
|
37
|
+
|
38
|
+
# Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile
|
39
|
+
# that contains the new image.
|
40
|
+
def make
|
41
|
+
src = @file
|
42
|
+
dst = Tempfile.new([@basename, @format].compact.join("."))
|
43
|
+
dst.binmode
|
44
|
+
|
45
|
+
command = <<-end_command
|
46
|
+
"#{ File.expand_path(src.path) }[0]"
|
47
|
+
#{ transformation_command }
|
48
|
+
"#{ File.expand_path(dst.path) }"
|
49
|
+
end_command
|
50
|
+
|
51
|
+
begin
|
52
|
+
success = Paperclip.run("convert", command.gsub(/\s+/, " "))
|
53
|
+
rescue PaperclipCommandLineError
|
54
|
+
raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny
|
55
|
+
end
|
56
|
+
|
57
|
+
dst
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the command ImageMagick's +convert+ needs to transform the image
|
61
|
+
# into the thumbnail.
|
62
|
+
def transformation_command
|
63
|
+
scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
|
64
|
+
trans = "-resize \"#{scale}\""
|
65
|
+
trans << " -crop \"#{crop}\" +repage" if crop
|
66
|
+
trans << " #{convert_options}" if convert_options?
|
67
|
+
trans
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,48 @@
|
|
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").downcase
|
10
|
+
case type
|
11
|
+
when %r"jpe?g" then "image/jpeg"
|
12
|
+
when %r"tiff?" then "image/tiff"
|
13
|
+
when %r"png", "gif", "bmp" then "image/#{type}"
|
14
|
+
when "txt" then "text/plain"
|
15
|
+
when %r"html?" then "text/html"
|
16
|
+
when "csv", "xml", "css", "js" then "text/#{type}"
|
17
|
+
else "application/x-#{type}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the file's normal name.
|
22
|
+
def original_filename
|
23
|
+
File.basename(self.path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the size of the file.
|
27
|
+
def size
|
28
|
+
File.size(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if defined? StringIO
|
34
|
+
class StringIO
|
35
|
+
attr_accessor :original_filename, :content_type
|
36
|
+
def original_filename
|
37
|
+
@original_filename ||= "stringio.txt"
|
38
|
+
end
|
39
|
+
def content_type
|
40
|
+
@content_type ||= "text/plain"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class File #:nodoc:
|
46
|
+
include Paperclip::Upfile
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'paperclip/matchers'
|
2
|
+
|
3
|
+
module Paperclip
|
4
|
+
# =Paperclip Shoulda Macros
|
5
|
+
#
|
6
|
+
# These macros are intended for use with shoulda, and will be included into
|
7
|
+
# your tests automatically. All of the macros use the standard shoulda
|
8
|
+
# assumption that the name of the test is based on the name of the model
|
9
|
+
# you're testing (that is, UserTest is the test for the User model), and
|
10
|
+
# will load that class for testing purposes.
|
11
|
+
module Shoulda
|
12
|
+
include Matchers
|
13
|
+
# This will test whether you have defined your attachment correctly by
|
14
|
+
# checking for all the required fields exist after the definition of the
|
15
|
+
# attachment.
|
16
|
+
def should_have_attached_file name
|
17
|
+
klass = self.name.gsub(/Test$/, '').constantize
|
18
|
+
matcher = have_attached_file name
|
19
|
+
should matcher.description do
|
20
|
+
assert_accepts(matcher, klass)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Tests for validations on the presence of the attachment.
|
25
|
+
def should_validate_attachment_presence name
|
26
|
+
klass = self.name.gsub(/Test$/, '').constantize
|
27
|
+
matcher = validate_attachment_presence name
|
28
|
+
should matcher.description do
|
29
|
+
assert_accepts(matcher, klass)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Tests that you have content_type validations specified. There are two
|
34
|
+
# options, :valid and :invalid. Both accept an array of strings. The
|
35
|
+
# strings should be a list of content types which will pass and fail
|
36
|
+
# validation, respectively.
|
37
|
+
def should_validate_attachment_content_type name, options = {}
|
38
|
+
klass = self.name.gsub(/Test$/, '').constantize
|
39
|
+
valid = [options[:valid]].flatten
|
40
|
+
invalid = [options[:invalid]].flatten
|
41
|
+
matcher = validate_attachment_content_type(name).allowing(valid).rejecting(invalid)
|
42
|
+
should matcher.description do
|
43
|
+
assert_accepts(matcher, klass)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Tests to ensure that you have file size validations turned on. You
|
48
|
+
# can pass the same options to this that you can to
|
49
|
+
# validate_attachment_file_size - :less_than, :greater_than, and :in.
|
50
|
+
# :less_than checks that a file is less than a certain size, :greater_than
|
51
|
+
# checks that a file is more than a certain size, and :in takes a Range or
|
52
|
+
# Array which specifies the lower and upper limits of the file size.
|
53
|
+
def should_validate_attachment_size name, options = {}
|
54
|
+
klass = self.name.gsub(/Test$/, '').constantize
|
55
|
+
min = options[:greater_than] || (options[:in] && options[:in].first) || 0
|
56
|
+
max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
|
57
|
+
range = (min..max)
|
58
|
+
matcher = validate_attachment_size(name).in(range)
|
59
|
+
should matcher.description do
|
60
|
+
assert_accepts(matcher, klass)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Test::Unit::TestCase #:nodoc:
|
67
|
+
extend Paperclip::Shoulda
|
68
|
+
end
|
@@ -0,0 +1,79 @@
|
|
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
|
+
def for_all_attachments
|
18
|
+
klass = obtain_class
|
19
|
+
names = obtain_attachments
|
20
|
+
ids = klass.connection.select_values(klass.send(:construct_finder_sql, :select => 'id'))
|
21
|
+
|
22
|
+
ids.each do |id|
|
23
|
+
instance = klass.find(id)
|
24
|
+
names.each do |name|
|
25
|
+
result = if instance.send("#{ name }?")
|
26
|
+
yield(instance, name)
|
27
|
+
else
|
28
|
+
true
|
29
|
+
end
|
30
|
+
print result ? "." : "x"; $stdout.flush
|
31
|
+
end
|
32
|
+
end
|
33
|
+
puts " Done."
|
34
|
+
end
|
35
|
+
|
36
|
+
namespace :paperclip do
|
37
|
+
desc "Refreshes both metadata and thumbnails."
|
38
|
+
task :refresh => ["paperclip:refresh:metadata", "paperclip:refresh:thumbnails"]
|
39
|
+
|
40
|
+
namespace :refresh do
|
41
|
+
desc "Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)."
|
42
|
+
task :thumbnails => :environment do
|
43
|
+
errors = []
|
44
|
+
for_all_attachments do |instance, name|
|
45
|
+
result = instance.send(name).reprocess!
|
46
|
+
errors << [instance.id, instance.errors] unless instance.errors.blank?
|
47
|
+
result
|
48
|
+
end
|
49
|
+
errors.each{|e| puts "#{e.first}: #{e.last.full_messages.inspect}" }
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT)."
|
53
|
+
task :metadata => :environment do
|
54
|
+
for_all_attachments do |instance, name|
|
55
|
+
if file = instance.send(name).to_file
|
56
|
+
instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip)
|
57
|
+
instance.send("#{name}_content_type=", file.content_type.strip)
|
58
|
+
instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size")
|
59
|
+
instance.save(false)
|
60
|
+
else
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "Cleans out invalid attachments. Useful after you've added new validations."
|
68
|
+
task :clean => :environment do
|
69
|
+
for_all_attachments do |instance, name|
|
70
|
+
instance.send(name).send(:validate)
|
71
|
+
if instance.send(name).valid?
|
72
|
+
true
|
73
|
+
else
|
74
|
+
instance.send("#{name}=", nil)
|
75
|
+
instance.save
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: betelgeuse-paperclip
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.8.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Yurek
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-02 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: right_aws
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thoughtbot-shoulda
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: mocha
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description:
|
46
|
+
email: jyurek@thoughtbot.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README.rdoc
|
53
|
+
files:
|
54
|
+
- README.rdoc
|
55
|
+
- LICENSE
|
56
|
+
- Rakefile
|
57
|
+
- init.rb
|
58
|
+
- generators/paperclip
|
59
|
+
- generators/paperclip/paperclip_generator.rb
|
60
|
+
- generators/paperclip/templates
|
61
|
+
- generators/paperclip/templates/paperclip_migration.rb.erb
|
62
|
+
- generators/paperclip/USAGE
|
63
|
+
- lib/paperclip
|
64
|
+
- lib/paperclip/attachment.rb
|
65
|
+
- lib/paperclip/callback_compatability.rb
|
66
|
+
- lib/paperclip/geometry.rb
|
67
|
+
- lib/paperclip/iostream.rb
|
68
|
+
- lib/paperclip/matchers
|
69
|
+
- lib/paperclip/matchers/have_attached_file_matcher.rb
|
70
|
+
- lib/paperclip/matchers/validate_attachment_content_type_matcher.rb
|
71
|
+
- lib/paperclip/matchers/validate_attachment_presence_matcher.rb
|
72
|
+
- lib/paperclip/matchers/validate_attachment_size_matcher.rb
|
73
|
+
- lib/paperclip/matchers.rb
|
74
|
+
- lib/paperclip/processor.rb
|
75
|
+
- lib/paperclip/storage.rb
|
76
|
+
- lib/paperclip/thumbnail.rb
|
77
|
+
- lib/paperclip/upfile.rb
|
78
|
+
- lib/paperclip.rb
|
79
|
+
- tasks/paperclip_tasks.rake
|
80
|
+
- shoulda_macros/paperclip.rb
|
81
|
+
has_rdoc: true
|
82
|
+
homepage: http://www.thoughtbot.com/projects/paperclip
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options:
|
85
|
+
- --line-numbers
|
86
|
+
- --inline-source
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
version:
|
101
|
+
requirements:
|
102
|
+
- ImageMagick
|
103
|
+
rubyforge_project: paperclip
|
104
|
+
rubygems_version: 1.2.0
|
105
|
+
signing_key:
|
106
|
+
specification_version: 2
|
107
|
+
summary: File attachments as attributes for ActiveRecord
|
108
|
+
test_files: []
|
109
|
+
|