kt-paperclip 6.2.0
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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +3 -0
- data/.gitignore +19 -0
- data/.hound.yml +1050 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +47 -0
- data/Appraisals +24 -0
- data/CONTRIBUTING.md +86 -0
- data/Gemfile +18 -0
- data/LICENSE +24 -0
- data/NEWS +515 -0
- data/README.md +1053 -0
- data/RELEASING.md +17 -0
- data/Rakefile +52 -0
- data/UPGRADING +17 -0
- data/features/basic_integration.feature +85 -0
- data/features/migration.feature +29 -0
- data/features/rake_tasks.feature +62 -0
- data/features/step_definitions/attachment_steps.rb +110 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +257 -0
- data/features/step_definitions/s3_steps.rb +14 -0
- data/features/step_definitions/web_steps.rb +106 -0
- data/features/support/env.rb +12 -0
- data/features/support/fakeweb.rb +11 -0
- data/features/support/file_helpers.rb +34 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +39 -0
- data/features/support/selectors.rb +19 -0
- data/gemfiles/4.2.gemfile +20 -0
- data/gemfiles/5.0.gemfile +20 -0
- data/gemfiles/5.1.gemfile +20 -0
- data/gemfiles/5.2.gemfile +20 -0
- data/gemfiles/6.0.gemfile +20 -0
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +36 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
- data/lib/paperclip.rb +215 -0
- data/lib/paperclip/attachment.rb +617 -0
- data/lib/paperclip/attachment_registry.rb +60 -0
- data/lib/paperclip/callbacks.rb +42 -0
- data/lib/paperclip/content_type_detector.rb +80 -0
- data/lib/paperclip/errors.rb +34 -0
- data/lib/paperclip/file_command_content_type_detector.rb +28 -0
- data/lib/paperclip/filename_cleaner.rb +15 -0
- data/lib/paperclip/geometry.rb +157 -0
- data/lib/paperclip/geometry_detector_factory.rb +45 -0
- data/lib/paperclip/geometry_parser_factory.rb +31 -0
- data/lib/paperclip/glue.rb +17 -0
- data/lib/paperclip/has_attached_file.rb +116 -0
- data/lib/paperclip/helpers.rb +60 -0
- data/lib/paperclip/interpolations.rb +201 -0
- data/lib/paperclip/interpolations/plural_cache.rb +18 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +47 -0
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
- data/lib/paperclip/io_adapters/registry.rb +36 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
- data/lib/paperclip/io_adapters/uri_adapter.rb +68 -0
- data/lib/paperclip/locales/en.yml +18 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers.rb +64 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
- data/lib/paperclip/media_type_spoof_detector.rb +90 -0
- data/lib/paperclip/missing_attachment_styles.rb +84 -0
- data/lib/paperclip/processor.rb +56 -0
- data/lib/paperclip/processor_helpers.rb +52 -0
- data/lib/paperclip/rails_environment.rb +21 -0
- data/lib/paperclip/railtie.rb +31 -0
- data/lib/paperclip/schema.rb +81 -0
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/storage/filesystem.rb +99 -0
- data/lib/paperclip/storage/fog.rb +252 -0
- data/lib/paperclip/storage/s3.rb +461 -0
- data/lib/paperclip/style.rb +106 -0
- data/lib/paperclip/tempfile.rb +42 -0
- data/lib/paperclip/tempfile_factory.rb +22 -0
- data/lib/paperclip/thumbnail.rb +131 -0
- data/lib/paperclip/url_generator.rb +76 -0
- data/lib/paperclip/validators.rb +73 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
- data/lib/paperclip/validators/attachment_file_name_validator.rb +75 -0
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +109 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
- data/lib/paperclip/version.rb +3 -0
- data/lib/tasks/paperclip.rake +140 -0
- data/paperclip.gemspec +50 -0
- data/shoulda_macros/paperclip.rb +134 -0
- data/spec/database.yml +4 -0
- data/spec/paperclip/attachment_definitions_spec.rb +13 -0
- data/spec/paperclip/attachment_processing_spec.rb +79 -0
- data/spec/paperclip/attachment_registry_spec.rb +158 -0
- data/spec/paperclip/attachment_spec.rb +1590 -0
- data/spec/paperclip/content_type_detector_spec.rb +47 -0
- data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
- data/spec/paperclip/filename_cleaner_spec.rb +13 -0
- data/spec/paperclip/geometry_detector_spec.rb +38 -0
- data/spec/paperclip/geometry_parser_spec.rb +73 -0
- data/spec/paperclip/geometry_spec.rb +255 -0
- data/spec/paperclip/glue_spec.rb +42 -0
- data/spec/paperclip/has_attached_file_spec.rb +78 -0
- data/spec/paperclip/integration_spec.rb +702 -0
- data/spec/paperclip/interpolations_spec.rb +270 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +140 -0
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +137 -0
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
- data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +221 -0
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
- data/spec/paperclip/paperclip_spec.rb +196 -0
- data/spec/paperclip/plural_cache_spec.rb +37 -0
- data/spec/paperclip/processor_helpers_spec.rb +57 -0
- data/spec/paperclip/processor_spec.rb +26 -0
- data/spec/paperclip/rails_environment_spec.rb +30 -0
- data/spec/paperclip/rake_spec.rb +103 -0
- data/spec/paperclip/schema_spec.rb +252 -0
- data/spec/paperclip/storage/filesystem_spec.rb +79 -0
- data/spec/paperclip/storage/fog_spec.rb +560 -0
- data/spec/paperclip/storage/s3_live_spec.rb +188 -0
- data/spec/paperclip/storage/s3_spec.rb +1695 -0
- data/spec/paperclip/style_spec.rb +251 -0
- data/spec/paperclip/tempfile_factory_spec.rb +33 -0
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +504 -0
- data/spec/paperclip/url_generator_spec.rb +221 -0
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +159 -0
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +235 -0
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
- data/spec/paperclip/validators_spec.rb +164 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/assertions.rb +84 -0
- data/spec/support/fake_model.rb +24 -0
- data/spec/support/fake_rails.rb +12 -0
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/bad.png +1 -0
- data/spec/support/fixtures/empty.html +1 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +8 -0
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/s3.yml +8 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +1 -0
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +5 -0
- data/spec/support/matchers/exist.rb +5 -0
- data/spec/support/matchers/have_column.rb +23 -0
- data/spec/support/mock_attachment.rb +24 -0
- data/spec/support/mock_interpolator.rb +24 -0
- data/spec/support/mock_url_generator_builder.rb +26 -0
- data/spec/support/model_reconstruction.rb +72 -0
- data/spec/support/reporting.rb +11 -0
- data/spec/support/test_data.rb +13 -0
- data/spec/support/version_helper.rb +9 -0
- metadata +586 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# The Style class holds the definition of a thumbnail style, applying
|
3
|
+
# whatever processing is required to normalize the definition and delaying
|
4
|
+
# the evaluation of block parameters until useful context is available.
|
5
|
+
|
6
|
+
class Style
|
7
|
+
attr_reader :name, :attachment, :format
|
8
|
+
|
9
|
+
# Creates a Style object. +name+ is the name of the attachment,
|
10
|
+
# +definition+ is the style definition from has_attached_file, which
|
11
|
+
# can be string, array or hash
|
12
|
+
def initialize(name, definition, attachment)
|
13
|
+
@name = name
|
14
|
+
@attachment = attachment
|
15
|
+
if definition.is_a? Hash
|
16
|
+
@geometry = definition.delete(:geometry)
|
17
|
+
@format = definition.delete(:format)
|
18
|
+
@processors = definition.delete(:processors)
|
19
|
+
@convert_options = definition.delete(:convert_options)
|
20
|
+
@source_file_options = definition.delete(:source_file_options)
|
21
|
+
@other_args = definition
|
22
|
+
elsif definition.is_a? String
|
23
|
+
@geometry = definition
|
24
|
+
@format = nil
|
25
|
+
@other_args = {}
|
26
|
+
else
|
27
|
+
@geometry, @format = [definition, nil].flatten[0..1]
|
28
|
+
@other_args = {}
|
29
|
+
end
|
30
|
+
@format = default_format if @format.blank?
|
31
|
+
end
|
32
|
+
|
33
|
+
# retrieves from the attachment the processors defined in the has_attached_file call
|
34
|
+
# (which method (in the attachment) will call any supplied procs)
|
35
|
+
# There is an important change of interface here: a style rule can set its own processors
|
36
|
+
# by default we behave as before, though.
|
37
|
+
# if a proc has been supplied, we call it here
|
38
|
+
def processors
|
39
|
+
@processors.respond_to?(:call) ? @processors.call(attachment.instance) : (@processors || attachment.processors)
|
40
|
+
end
|
41
|
+
|
42
|
+
# retrieves from the attachment the whiny setting
|
43
|
+
def whiny
|
44
|
+
attachment.whiny
|
45
|
+
end
|
46
|
+
|
47
|
+
# returns true if we're inclined to grumble
|
48
|
+
def whiny?
|
49
|
+
!!whiny
|
50
|
+
end
|
51
|
+
|
52
|
+
def convert_options
|
53
|
+
@convert_options.respond_to?(:call) ? @convert_options.call(attachment.instance) :
|
54
|
+
(@convert_options || attachment.send(:extra_options_for, name))
|
55
|
+
end
|
56
|
+
|
57
|
+
def source_file_options
|
58
|
+
@source_file_options.respond_to?(:call) ? @source_file_options.call(attachment.instance) :
|
59
|
+
(@source_file_options || attachment.send(:extra_source_file_options_for, name))
|
60
|
+
end
|
61
|
+
|
62
|
+
# returns the geometry string for this style
|
63
|
+
# if a proc has been supplied, we call it here
|
64
|
+
def geometry
|
65
|
+
@geometry.respond_to?(:call) ? @geometry.call(attachment.instance) : @geometry
|
66
|
+
end
|
67
|
+
|
68
|
+
# Supplies the hash of options that processors expect to receive as their second argument
|
69
|
+
# Arguments other than the standard geometry, format etc are just passed through from
|
70
|
+
# initialization and any procs are called here, just before post-processing.
|
71
|
+
def processor_options
|
72
|
+
args = { style: name }
|
73
|
+
@other_args.each do |k, v|
|
74
|
+
args[k] = v.respond_to?(:call) ? v.call(attachment) : v
|
75
|
+
end
|
76
|
+
[:processors, :geometry, :format, :whiny, :convert_options, :source_file_options].each do |k|
|
77
|
+
(arg = send(k)) && args[k] = arg
|
78
|
+
end
|
79
|
+
args
|
80
|
+
end
|
81
|
+
|
82
|
+
# Supports getting and setting style properties with hash notation to ensure backwards-compatibility
|
83
|
+
# eg. @attachment.styles[:large][:geometry]@ will still work
|
84
|
+
def [](key)
|
85
|
+
if [:name, :convert_options, :whiny, :processors, :geometry, :format, :animated, :source_file_options].include?(key)
|
86
|
+
send(key)
|
87
|
+
elsif defined? @other_args[key]
|
88
|
+
@other_args[key]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def []=(key, value)
|
93
|
+
if [:name, :convert_options, :whiny, :processors, :geometry, :format, :animated, :source_file_options].include?(key)
|
94
|
+
send("#{key}=".intern, value)
|
95
|
+
else
|
96
|
+
@other_args[key] = value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# defaults to default format (nil by default)
|
101
|
+
def default_format
|
102
|
+
base = attachment.options[:default_format]
|
103
|
+
base.respond_to?(:call) ? base.call(attachment, name) : base
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# Overriding some implementation of Tempfile
|
3
|
+
class Tempfile < ::Tempfile
|
4
|
+
# Due to how ImageMagick handles its image format conversion and how
|
5
|
+
# Tempfile handles its naming scheme, it is necessary to override how
|
6
|
+
# Tempfile makes # its names so as to allow for file extensions. Idea
|
7
|
+
# taken from the comments on this blog post:
|
8
|
+
# http://marsorange.com/archives/of-mogrify-ruby-tempfile-dynamic-class-definitions
|
9
|
+
#
|
10
|
+
# This is Ruby 1.9.3's implementation.
|
11
|
+
def make_tmpname(prefix_suffix, n)
|
12
|
+
if RUBY_PLATFORM =~ /java/
|
13
|
+
case prefix_suffix
|
14
|
+
when String
|
15
|
+
prefix = prefix_suffix
|
16
|
+
suffix = ""
|
17
|
+
when Array
|
18
|
+
prefix, suffix = *prefix_suffix
|
19
|
+
else
|
20
|
+
raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
t = Time.now.strftime("%y%m%d")
|
24
|
+
path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}"
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module TempfileEncoding
|
32
|
+
# This overrides Tempfile#binmode to make sure that the extenal encoding
|
33
|
+
# for binary mode is ASCII-8BIT. This behavior is what's in CRuby, but not
|
34
|
+
# in JRuby
|
35
|
+
def binmode
|
36
|
+
set_encoding("ASCII-8BIT")
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
::Tempfile.include Paperclip::TempfileEncoding if RUBY_PLATFORM =~ /java/
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class TempfileFactory
|
3
|
+
def generate(name = random_name)
|
4
|
+
@name = name
|
5
|
+
file = Tempfile.new([basename, extension])
|
6
|
+
file.binmode
|
7
|
+
file
|
8
|
+
end
|
9
|
+
|
10
|
+
def extension
|
11
|
+
File.extname(@name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def basename
|
15
|
+
Digest::MD5.hexdigest(File.basename(@name, extension))
|
16
|
+
end
|
17
|
+
|
18
|
+
def random_name
|
19
|
+
SecureRandom.uuid
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# Handles thumbnailing images that are uploaded.
|
3
|
+
class Thumbnail < Processor
|
4
|
+
attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options,
|
5
|
+
:source_file_options, :animated, :auto_orient, :frame_index
|
6
|
+
|
7
|
+
# List of formats that we need to preserve animation
|
8
|
+
ANIMATED_FORMATS = %w(gif).freeze
|
9
|
+
MULTI_FRAME_FORMATS = %w(.mkv .avi .mp4 .mov .mpg .mpeg .gif).freeze
|
10
|
+
|
11
|
+
# Creates a Thumbnail object set to work on the +file+ given. It
|
12
|
+
# will attempt to transform the image into one defined by +target_geometry+
|
13
|
+
# which is a "WxH"-style string. +format+ will be inferred from the +file+
|
14
|
+
# unless specified. Thumbnail creation will raise no errors unless
|
15
|
+
# +whiny+ is true (which it is, by default. If +convert_options+ is
|
16
|
+
# set, the options will be appended to the convert command upon image conversion
|
17
|
+
#
|
18
|
+
# Options include:
|
19
|
+
#
|
20
|
+
# +geometry+ - the desired width and height of the thumbnail (required)
|
21
|
+
# +file_geometry_parser+ - an object with a method named +from_file+ that takes an image file and produces its geometry and a +transformation_to+. Defaults to Paperclip::Geometry
|
22
|
+
# +string_geometry_parser+ - an object with a method named +parse+ that takes a string and produces an object with +width+, +height+, and +to_s+ accessors. Defaults to Paperclip::Geometry
|
23
|
+
# +source_file_options+ - flags passed to the +convert+ command that influence how the source file is read
|
24
|
+
# +convert_options+ - flags passed to the +convert+ command that influence how the image is processed
|
25
|
+
# +whiny+ - whether to raise an error when processing fails. Defaults to true
|
26
|
+
# +format+ - the desired filename extension
|
27
|
+
# +animated+ - whether to merge all the layers in the image. Defaults to true
|
28
|
+
# +frame_index+ - the frame index of the source file to render as the thumbnail
|
29
|
+
def initialize(file, options = {}, attachment = nil)
|
30
|
+
super
|
31
|
+
|
32
|
+
geometry = options[:geometry].to_s
|
33
|
+
@crop = geometry[-1, 1] == "#"
|
34
|
+
@target_geometry = options.fetch(:string_geometry_parser, Geometry).parse(geometry)
|
35
|
+
@current_geometry = options.fetch(:file_geometry_parser, Geometry).from_file(@file)
|
36
|
+
@source_file_options = options[:source_file_options]
|
37
|
+
@convert_options = options[:convert_options]
|
38
|
+
@whiny = options.fetch(:whiny, true)
|
39
|
+
@format = options[:format]
|
40
|
+
@animated = options.fetch(:animated, true)
|
41
|
+
@auto_orient = options.fetch(:auto_orient, true)
|
42
|
+
@current_geometry.auto_orient if @auto_orient && @current_geometry.respond_to?(:auto_orient)
|
43
|
+
@source_file_options = @source_file_options.split(/\s+/) if @source_file_options.respond_to?(:split)
|
44
|
+
@convert_options = @convert_options.split(/\s+/) if @convert_options.respond_to?(:split)
|
45
|
+
|
46
|
+
@current_format = File.extname(@file.path)
|
47
|
+
@basename = File.basename(@file.path, @current_format)
|
48
|
+
@frame_index = multi_frame_format? ? options.fetch(:frame_index, 0) : 0
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns true if the +target_geometry+ is meant to crop.
|
52
|
+
def crop?
|
53
|
+
@crop
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns true if the image is meant to make use of additional convert options.
|
57
|
+
def convert_options?
|
58
|
+
!@convert_options.nil? && !@convert_options.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile
|
62
|
+
# that contains the new image.
|
63
|
+
def make
|
64
|
+
src = @file
|
65
|
+
filename = [@basename, @format ? ".#{@format}" : ""].join
|
66
|
+
dst = TempfileFactory.new.generate(filename)
|
67
|
+
|
68
|
+
begin
|
69
|
+
parameters = []
|
70
|
+
parameters << source_file_options
|
71
|
+
parameters << ":source"
|
72
|
+
parameters << transformation_command
|
73
|
+
parameters << convert_options
|
74
|
+
parameters << ":dest"
|
75
|
+
|
76
|
+
parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")
|
77
|
+
|
78
|
+
frame = animated? ? "" : "[#{@frame_index}]"
|
79
|
+
convert(
|
80
|
+
parameters,
|
81
|
+
source: "#{File.expand_path(src.path)}#{frame}",
|
82
|
+
dest: File.expand_path(dst.path)
|
83
|
+
)
|
84
|
+
rescue Terrapin::ExitStatusError => e
|
85
|
+
if @whiny
|
86
|
+
message = "There was an error processing the thumbnail for #{@basename}:\n" + e.message
|
87
|
+
raise Paperclip::Error, message
|
88
|
+
end
|
89
|
+
rescue Terrapin::CommandNotFoundError => e
|
90
|
+
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `convert` command. Please install ImageMagick.")
|
91
|
+
end
|
92
|
+
|
93
|
+
dst
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the command ImageMagick's +convert+ needs to transform the image
|
97
|
+
# into the thumbnail.
|
98
|
+
def transformation_command
|
99
|
+
scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
|
100
|
+
trans = []
|
101
|
+
trans << "-coalesce" if animated?
|
102
|
+
trans << "-auto-orient" if auto_orient
|
103
|
+
trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
|
104
|
+
trans << "-crop" << %["#{crop}"] << "+repage" if crop
|
105
|
+
trans << '-layers "optimize"' if animated?
|
106
|
+
trans
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
def multi_frame_format?
|
112
|
+
MULTI_FRAME_FORMATS.include? @current_format
|
113
|
+
end
|
114
|
+
|
115
|
+
def animated?
|
116
|
+
@animated && (ANIMATED_FORMATS.include?(@format.to_s) || @format.blank?) && identified_as_animated?
|
117
|
+
end
|
118
|
+
|
119
|
+
# Return true if ImageMagick's +identify+ returns an animated format
|
120
|
+
def identified_as_animated?
|
121
|
+
if @identified_as_animated.nil?
|
122
|
+
@identified_as_animated = ANIMATED_FORMATS.include? identify("-format %m :file", file: "#{@file.path}[0]").to_s.downcase.strip
|
123
|
+
end
|
124
|
+
@identified_as_animated
|
125
|
+
rescue Terrapin::ExitStatusError => e
|
126
|
+
raise Paperclip::Error, "There was an error running `identify` for #{@basename}" if @whiny
|
127
|
+
rescue Terrapin::CommandNotFoundError => e
|
128
|
+
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "active_support/core_ext/module/delegation"
|
3
|
+
|
4
|
+
module Paperclip
|
5
|
+
class UrlGenerator
|
6
|
+
def initialize(attachment)
|
7
|
+
@attachment = attachment
|
8
|
+
end
|
9
|
+
|
10
|
+
def for(style_name, options)
|
11
|
+
interpolated = attachment_options[:interpolator].interpolate(
|
12
|
+
most_appropriate_url, @attachment, style_name
|
13
|
+
)
|
14
|
+
|
15
|
+
escaped = escape_url_as_needed(interpolated, options)
|
16
|
+
timestamp_as_needed(escaped, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :attachment
|
22
|
+
delegate :options, to: :attachment, prefix: true
|
23
|
+
|
24
|
+
# This method is all over the place.
|
25
|
+
def default_url
|
26
|
+
if attachment_options[:default_url].respond_to?(:call)
|
27
|
+
attachment_options[:default_url].call(@attachment)
|
28
|
+
elsif attachment_options[:default_url].is_a?(Symbol)
|
29
|
+
@attachment.instance.send(attachment_options[:default_url])
|
30
|
+
else
|
31
|
+
attachment_options[:default_url]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def most_appropriate_url
|
36
|
+
if @attachment.original_filename.nil?
|
37
|
+
default_url
|
38
|
+
else
|
39
|
+
attachment_options[:url]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def timestamp_as_needed(url, options)
|
44
|
+
if options[:timestamp] && timestamp_possible?
|
45
|
+
delimiter_char = url.match(/\?.+=/) ? "&" : "?"
|
46
|
+
"#{url}#{delimiter_char}#{@attachment.updated_at}"
|
47
|
+
else
|
48
|
+
url
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def timestamp_possible?
|
53
|
+
@attachment.respond_to?(:updated_at) && @attachment.updated_at.present?
|
54
|
+
end
|
55
|
+
|
56
|
+
def escape_url_as_needed(url, options)
|
57
|
+
if options[:escape]
|
58
|
+
escape_url(url)
|
59
|
+
else
|
60
|
+
url
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def escape_url(url)
|
65
|
+
if url.respond_to?(:escape)
|
66
|
+
url.escape
|
67
|
+
else
|
68
|
+
URI.escape(url).gsub(escape_regex) { |m| "%#{m.ord.to_s(16).upcase}" }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def escape_regex
|
73
|
+
/[\?\(\)\[\]\+]/
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "active_model"
|
2
|
+
require "active_support/concern"
|
3
|
+
require "active_support/core_ext/array/wrap"
|
4
|
+
require "paperclip/validators/attachment_content_type_validator"
|
5
|
+
require "paperclip/validators/attachment_file_name_validator"
|
6
|
+
require "paperclip/validators/attachment_presence_validator"
|
7
|
+
require "paperclip/validators/attachment_size_validator"
|
8
|
+
require "paperclip/validators/media_type_spoof_detection_validator"
|
9
|
+
require "paperclip/validators/attachment_file_type_ignorance_validator"
|
10
|
+
|
11
|
+
module Paperclip
|
12
|
+
module Validators
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
extend HelperMethods
|
17
|
+
include HelperMethods
|
18
|
+
end
|
19
|
+
|
20
|
+
::Paperclip::REQUIRED_VALIDATORS = [AttachmentFileNameValidator, AttachmentContentTypeValidator, AttachmentFileTypeIgnoranceValidator].freeze
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
# This method is a shortcut to validator classes that is in
|
24
|
+
# "Attachment...Validator" format. It is almost the same thing as the
|
25
|
+
# +validates+ method that shipped with Rails, but this is customized to
|
26
|
+
# be using with attachment validators. This is helpful when you're using
|
27
|
+
# multiple attachment validators on a single attachment.
|
28
|
+
#
|
29
|
+
# Example of using the validator:
|
30
|
+
#
|
31
|
+
# validates_attachment :avatar, :presence => true,
|
32
|
+
# :content_type => { :content_type => "image/jpg" },
|
33
|
+
# :size => { :in => 0..10.kilobytes }
|
34
|
+
#
|
35
|
+
def validates_attachment(*attributes)
|
36
|
+
options = attributes.extract_options!.dup
|
37
|
+
|
38
|
+
Paperclip::Validators.constants.each do |constant|
|
39
|
+
if constant.to_s =~ /\AAttachment(.+)Validator\z/
|
40
|
+
validator_kind = $1.underscore.to_sym
|
41
|
+
|
42
|
+
if options.key?(validator_kind)
|
43
|
+
validator_options = options.delete(validator_kind)
|
44
|
+
validator_options = {} if validator_options == true
|
45
|
+
conditional_options = options.slice(:if, :unless)
|
46
|
+
Array.wrap(validator_options).each do |local_options|
|
47
|
+
method_name = Paperclip::Validators.const_get(constant.to_s).helper_method_name
|
48
|
+
send(method_name, attributes, local_options.merge(conditional_options))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_before_processing(validator_class, options)
|
56
|
+
options = options.dup
|
57
|
+
attributes = options.delete(:attributes)
|
58
|
+
attributes.each do |attribute|
|
59
|
+
options[:attributes] = [attribute]
|
60
|
+
create_validating_before_filter(attribute, validator_class, options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_validating_before_filter(attribute, validator_class, options)
|
65
|
+
if_clause = options.delete(:if)
|
66
|
+
unless_clause = options.delete(:unless)
|
67
|
+
send(:"before_#{attribute}_validate", if: if_clause, unless: unless_clause) do |*_args|
|
68
|
+
validator_class.new(options.dup).validate(self)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|