paperclip 5.0.0 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/NEWS +8 -0
- data/README.md +57 -53
- data/features/basic_integration.feature +2 -2
- data/lib/paperclip/attachment.rb +5 -2
- data/lib/paperclip/interpolations.rb +1 -1
- data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/uri_adapter.rb +30 -12
- data/lib/paperclip/processor.rb +5 -4
- data/lib/paperclip/storage/fog.rb +2 -2
- data/lib/paperclip/storage/s3.rb +13 -15
- data/lib/paperclip/url_generator.rb +16 -13
- data/lib/paperclip/validators.rb +1 -1
- data/lib/paperclip/version.rb +1 -1
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +9 -6
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +2 -2
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +45 -7
- data/spec/paperclip/storage/s3_spec.rb +62 -33
- data/spec/paperclip/url_generator_spec.rb +54 -43
- data/spec/paperclip/validators_spec.rb +2 -2
- data/spec/support/mock_attachment.rb +2 -0
- data/spec/support/mock_url_generator_builder.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70e53f15c9fc9e1ffd3097f25a2fd58de617aa80
|
4
|
+
data.tar.gz: 5c2d008914407061d105a5b18d97e9c4e0c88c74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 368a451123ff0522cf60676a0925d2b69b6529db7ad4ef91ff03f41ef08910016a9d1715c618d90f451754982395259264be9869f290fd91591c7723b3a23f7b
|
7
|
+
data.tar.gz: b69604376b66abe5a599fef4c72be3771822d6bb9f05a3732b2e5a91853ff61fc659f77541bafcb219bd5d5f15fcd61f79134ee654714e36b2a795d7da9c8198
|
data/NEWS
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
master:
|
2
2
|
|
3
|
+
* Add default `content_type_detector` to `UploadedFileAdapter` (#2270)
|
4
|
+
* Default S3 protocol to empty string (#2038)
|
5
|
+
* Don't write original file if it wasn't reprocessed (#1993)
|
6
|
+
* Disallow trailing newlines in regular expressions (#2266)
|
7
|
+
* Support for readbyte in Paperclip attachments (#2034)
|
8
|
+
* (port from 4.3) Uri io adapter uses the content-disposition filename (#2250)
|
9
|
+
* General refactors and documentation improvements
|
10
|
+
|
3
11
|
5.0.0 (2016-07-01):
|
4
12
|
|
5
13
|
* Improvement: Add `read_timeout` configuration for URI Adapter download_content method.
|
data/README.md
CHANGED
@@ -43,11 +43,11 @@ https://github.com/thoughtbot/paperclip/releases
|
|
43
43
|
- [Storage](#storage)
|
44
44
|
- [Understanding Storage](#understanding-storage)
|
45
45
|
- [Post Processing](#post-processing)
|
46
|
+
- [Custom Attachment Processors](#custom-attachment-processors)
|
46
47
|
- [Events](#events)
|
47
48
|
- [URI Obfuscation](#uri-obfuscation)
|
48
49
|
- [MD5 Checksum / Fingerprint](#md5-checksum--fingerprint)
|
49
50
|
- [File Preservation for Soft-Delete](#file-preservation-for-soft-delete)
|
50
|
-
- [Custom Attachment Processors](#custom-attachment-processors)
|
51
51
|
- [Dynamic Configuration](#dynamic-configuration)
|
52
52
|
- [Dynamic Styles:](#dynamic-styles)
|
53
53
|
- [Dynamic Processors:](#dynamic-processors)
|
@@ -199,7 +199,7 @@ Quick Start
|
|
199
199
|
```ruby
|
200
200
|
class User < ActiveRecord::Base
|
201
201
|
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
|
202
|
-
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\
|
202
|
+
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
|
203
203
|
end
|
204
204
|
```
|
205
205
|
|
@@ -260,6 +260,16 @@ end
|
|
260
260
|
<%= image_tag @user.avatar.url(:thumb) %>
|
261
261
|
```
|
262
262
|
|
263
|
+
### Checking a file exists
|
264
|
+
|
265
|
+
There are two methods for checking if a file exists:
|
266
|
+
|
267
|
+
- `file?` and `present?` checks if the `_file_name` field is populated
|
268
|
+
- `exists?` checks if the file exists (will perform a TCP connection if stored in the cloud)
|
269
|
+
|
270
|
+
Keep this in mind if you are checking if files are present in a loop. The first
|
271
|
+
version is significantly more performant, but has different semantics.
|
272
|
+
|
263
273
|
### Deleting an Attachment
|
264
274
|
|
265
275
|
Set the attribute to `nil` and save.
|
@@ -417,7 +427,7 @@ class ActiveRecord::Base
|
|
417
427
|
# Validate content type
|
418
428
|
validates_attachment_content_type :avatar, content_type: /\Aimage/
|
419
429
|
# Validate filename
|
420
|
-
validates_attachment_file_name :avatar, matches: [/png\
|
430
|
+
validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
|
421
431
|
# Explicitly do not validate
|
422
432
|
do_not_validate_attachment_file_type :avatar
|
423
433
|
end
|
@@ -558,6 +568,7 @@ Paperclip ships with 3 storage adapters:
|
|
558
568
|
If you would like to use Paperclip with another storage, you can install these
|
559
569
|
gems along side with Paperclip:
|
560
570
|
|
571
|
+
* [paperclip-azure](https://github.com/supportify/paperclip-azure)
|
561
572
|
* [paperclip-azure-storage](https://github.com/gmontard/paperclip-azure-storage)
|
562
573
|
* [paperclip-dropbox](https://github.com/janko-m/paperclip-dropbox)
|
563
574
|
|
@@ -601,60 +612,72 @@ Post Processing
|
|
601
612
|
|
602
613
|
Paperclip supports an extensible selection of post-processors. When you define
|
603
614
|
a set of styles for an attachment, by default it is expected that those
|
604
|
-
"styles" are actually "thumbnails."
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
automatically loaded by Paperclip, allowing you to easily define custom
|
609
|
-
processors. You can specify a processor with the `:processors` option to
|
610
|
-
`has_attached_file`:
|
615
|
+
"styles" are actually "thumbnails." These are processed by
|
616
|
+
`Paperclip::Thumbnail`. For backward compatibility reasons you can pass either
|
617
|
+
a single geometry string, or an array containing a geometry and a format that
|
618
|
+
the file will be converted to, like so:
|
611
619
|
|
612
620
|
```ruby
|
613
|
-
has_attached_file :
|
614
|
-
processors: [:ocr]
|
621
|
+
has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }
|
615
622
|
```
|
616
623
|
|
617
|
-
This
|
618
|
-
|
619
|
-
|
620
|
-
[
|
624
|
+
This will convert the "thumb" style to a 32x32 square in PNG format, regardless
|
625
|
+
of what was uploaded. If the format is not specified, it is kept the same (e.g.
|
626
|
+
JPGs will remain JPGs). `Paperclip::Thumbnail` uses ImageMagick to process
|
627
|
+
images; [ImageMagick's geometry documentation](http://www.imagemagick.org/script/command-line-processing.php#geometry)
|
628
|
+
has more information on the accepted style formats.
|
629
|
+
|
630
|
+
---
|
631
|
+
|
632
|
+
Custom Attachment Processors
|
633
|
+
-------
|
621
634
|
|
622
|
-
|
623
|
-
|
624
|
-
|
635
|
+
You can write your own custom attachment processors to carry out tasks like
|
636
|
+
adding watermarks, compressing images, or encrypting files. Custom processors
|
637
|
+
must be defined within the `Paperclip` module, inherit from
|
638
|
+
`Paperclip::Processor` (see [`lib/paperclip/processor.rb`](https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb)),
|
639
|
+
and implement a `make` method that returns a `File`. All files in your Rails
|
640
|
+
app's `lib/paperclip` and `lib/paperclip_processors` directories will be
|
641
|
+
automatically loaded by Paperclip. Processors are specified using the
|
642
|
+
`:processors` option to `has_attached_file`:
|
625
643
|
|
626
644
|
```ruby
|
627
|
-
has_attached_file :
|
645
|
+
has_attached_file :scan, styles: { text: { quality: :better } },
|
646
|
+
processors: [:ocr]
|
628
647
|
```
|
629
648
|
|
630
|
-
This
|
631
|
-
|
632
|
-
JPGs will remain JPGs). For more information on the accepted style formats, see
|
633
|
-
[here](http://www.imagemagick.org/script/command-line-processing.php#geometry).
|
649
|
+
This would load the hypothetical class `Paperclip::Ocr`, and pass it the
|
650
|
+
options hash `{ quality: :better }`, along with the uploaded file.
|
634
651
|
|
635
652
|
Multiple processors can be specified, and they will be invoked in the order
|
636
|
-
they are defined in the `:processors` array. Each successive processor
|
637
|
-
|
638
|
-
|
639
|
-
|
653
|
+
they are defined in the `:processors` array. Each successive processor is given
|
654
|
+
the result from the previous processor. All processors receive the same
|
655
|
+
parameters, which are defined in the `:styles` hash. For example, assuming we
|
656
|
+
had this definition:
|
640
657
|
|
641
658
|
```ruby
|
642
659
|
has_attached_file :scan, styles: { text: { quality: :better } },
|
643
660
|
processors: [:rotator, :ocr]
|
644
661
|
```
|
645
662
|
|
646
|
-
|
647
|
-
options `{ quality: :better }`.
|
648
|
-
|
663
|
+
Both the `:rotator` processor and the `:ocr` processor would receive the
|
664
|
+
options `{ quality: :better }`. If a processor receives an option it doesn't
|
665
|
+
recognise, it's expected to ignore it.
|
649
666
|
|
650
667
|
_NOTE: Because processors operate by turning the original attachment into the
|
651
668
|
styles, no processors will be run if there are no styles defined._
|
652
669
|
|
653
670
|
If you're interested in caching your thumbnail's width, height and size in the
|
654
|
-
database, take a look at the [paperclip-meta](https://github.com/teeparham/paperclip-meta)
|
671
|
+
database, take a look at the [paperclip-meta](https://github.com/teeparham/paperclip-meta)
|
672
|
+
gem.
|
655
673
|
|
656
674
|
Also, if you're interested in generating the thumbnail on-the-fly, you might want
|
657
|
-
to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly)
|
675
|
+
to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly)
|
676
|
+
gem.
|
677
|
+
|
678
|
+
Paperclip's thumbnail generator (see [`lib/paperclip/thumbnail.rb`](lib/paperclip/thumbnail.rb))
|
679
|
+
is implemented as a processor, and may be a good reference for writing your own
|
680
|
+
processors.
|
658
681
|
|
659
682
|
---
|
660
683
|
|
@@ -739,7 +762,7 @@ An option is available to preserve attachments in order to play nicely with soft
|
|
739
762
|
|
740
763
|
```ruby
|
741
764
|
has_attached_file :some_attachment, {
|
742
|
-
preserve_files:
|
765
|
+
preserve_files: true,
|
743
766
|
}
|
744
767
|
```
|
745
768
|
|
@@ -747,25 +770,6 @@ This will prevent ```some_attachment``` from being wiped out when the model gets
|
|
747
770
|
|
748
771
|
---
|
749
772
|
|
750
|
-
Custom Attachment Processors
|
751
|
-
-------
|
752
|
-
|
753
|
-
Custom attachment processors can be implemented and their only requirement is
|
754
|
-
to inherit from `Paperclip::Processor` (see `lib/paperclip/processor.rb`).
|
755
|
-
For example, when `:styles` are specified for an image attachment, the
|
756
|
-
thumbnail processor (see `lib/paperclip/thumbnail.rb`) is loaded without having
|
757
|
-
to specify it as a `:processor` parameter to `has_attached_file`. When any
|
758
|
-
other processor is defined, it must be called out in the `:processors`
|
759
|
-
parameter if it is to be applied to the attachment. The thumbnail processor
|
760
|
-
uses the ImageMagick `convert` command to do the work of resizing image
|
761
|
-
thumbnails. It would be easy to create a custom processor that watermarks
|
762
|
-
an image using ImageMagick's `composite` command. Following the
|
763
|
-
implementation pattern of the thumbnail processor would be a way to implement a
|
764
|
-
watermark processor. All kinds of attachment processors can be created;
|
765
|
-
a few utility examples would be compression and encryption processors.
|
766
|
-
|
767
|
-
---
|
768
|
-
|
769
773
|
Dynamic Configuration
|
770
774
|
---------------------
|
771
775
|
|
@@ -77,5 +77,5 @@ Feature: Rails integration
|
|
77
77
|
And I attach the file "spec/support/fixtures/5k.png" to "Attachment" on S3
|
78
78
|
And I press "Submit"
|
79
79
|
Then I should see "Name: something"
|
80
|
-
And I should see an image with a path of "
|
81
|
-
And the file at "
|
80
|
+
And I should see an image with a path of "//s3.amazonaws.com/paperclip/attachments/original/5k.png"
|
81
|
+
And the file at "//s3.amazonaws.com/paperclip/attachments/original/5k.png" should be uploaded to S3
|
data/lib/paperclip/attachment.rb
CHANGED
@@ -50,7 +50,7 @@ module Paperclip
|
|
50
50
|
# +url+ - a relative URL of the attachment. This is interpolated using +interpolator+
|
51
51
|
# +path+ - where on the filesystem to store the attachment. This is interpolated using +interpolator+
|
52
52
|
# +styles+ - a hash of options for processing the attachment. See +has_attached_file+ for the details
|
53
|
-
# +only_process+ - style args to be run through the post-processor. This defaults to the empty list (which is
|
53
|
+
# +only_process+ - style args to be run through the post-processor. This defaults to the empty list (which is
|
54
54
|
# a special case that indicates all styles should be processed)
|
55
55
|
# +default_url+ - a URL for the missing image
|
56
56
|
# +default_style+ - the style to use when an argument is not specified e.g. #url, #path
|
@@ -83,7 +83,7 @@ module Paperclip
|
|
83
83
|
@errors = {}
|
84
84
|
@dirty = false
|
85
85
|
@interpolator = options[:interpolator]
|
86
|
-
@url_generator = options[:url_generator].new(self
|
86
|
+
@url_generator = options[:url_generator].new(self)
|
87
87
|
@source_file_options = options[:source_file_options]
|
88
88
|
@whiny = options[:whiny]
|
89
89
|
|
@@ -238,6 +238,9 @@ module Paperclip
|
|
238
238
|
# the instance's errors and returns false, cancelling the save.
|
239
239
|
def save
|
240
240
|
flush_deletes unless @options[:keep_old_files]
|
241
|
+
if @options[:only_process].any? && !@options[:only_process].include?(:original)
|
242
|
+
@queued_for_write.except!(:original)
|
243
|
+
end
|
241
244
|
flush_writes
|
242
245
|
@dirty = false
|
243
246
|
true
|
@@ -141,7 +141,7 @@ module Paperclip
|
|
141
141
|
# It's possible, though unlikely, that the mime type is not in the
|
142
142
|
# database, so just use the part after the '/' in the mime type as the
|
143
143
|
# extension.
|
144
|
-
%r{/([^/]*)\
|
144
|
+
%r{/([^/]*)\z}.match(attachment.content_type)[1]
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -5,7 +5,7 @@ module Paperclip
|
|
5
5
|
OS_RESTRICTED_CHARACTERS = %r{[/:]}
|
6
6
|
|
7
7
|
attr_reader :content_type, :original_filename, :size
|
8
|
-
delegate :binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :rewind, :unlink, :to => :@tempfile
|
8
|
+
delegate :binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink, :to => :@tempfile
|
9
9
|
alias :length :size
|
10
10
|
|
11
11
|
def fingerprint
|
@@ -2,6 +2,8 @@ require 'open-uri'
|
|
2
2
|
|
3
3
|
module Paperclip
|
4
4
|
class UriAdapter < AbstractAdapter
|
5
|
+
attr_writer :content_type
|
6
|
+
|
5
7
|
def initialize(target)
|
6
8
|
@target = target
|
7
9
|
@content = download_content
|
@@ -9,25 +11,41 @@ module Paperclip
|
|
9
11
|
@tempfile = copy_to_tempfile(@content)
|
10
12
|
end
|
11
13
|
|
12
|
-
attr_writer :content_type
|
13
|
-
|
14
14
|
private
|
15
15
|
|
16
|
-
def
|
17
|
-
|
16
|
+
def cache_current_values
|
17
|
+
self.content_type = content_type_from_content || "text/html"
|
18
18
|
|
19
|
-
|
19
|
+
self.original_filename = filename_from_content_disposition ||
|
20
|
+
filename_from_path || default_filename
|
21
|
+
@size = @content.size
|
20
22
|
end
|
21
23
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def content_type_from_content
|
25
|
+
if @content.respond_to?(:content_type)
|
26
|
+
@content.content_type
|
27
|
+
end
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
@
|
30
|
+
def filename_from_content_disposition
|
31
|
+
if @content.meta.has_key?("content-disposition")
|
32
|
+
@content.meta["content-disposition"].
|
33
|
+
match(/filename="([^"]*)"/)[1]
|
34
|
+
end
|
35
|
+
end
|
29
36
|
|
30
|
-
|
37
|
+
def filename_from_path
|
38
|
+
@target.path.split("/").last
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_filename
|
42
|
+
"index.html"
|
43
|
+
end
|
44
|
+
|
45
|
+
def download_content
|
46
|
+
options = { read_timeout: Paperclip.options[:read_timeout] }.compact
|
47
|
+
|
48
|
+
open(@target, **options)
|
31
49
|
end
|
32
50
|
|
33
51
|
def copy_to_tempfile(src)
|
data/lib/paperclip/processor.rb
CHANGED
@@ -7,13 +7,14 @@ module Paperclip
|
|
7
7
|
# Processors are required to be defined inside the Paperclip module and
|
8
8
|
# are also required to be a subclass of Paperclip::Processor. There is
|
9
9
|
# only one method you *must* implement to properly be a subclass:
|
10
|
-
# #make, but #initialize may also be of use.
|
10
|
+
# #make, but #initialize may also be of use. #initialize accepts 3
|
11
11
|
# arguments: the file that will be operated on (which is an instance of
|
12
12
|
# File), a hash of options that were defined in has_attached_file's
|
13
|
-
# style hash, and the Paperclip::Attachment itself.
|
13
|
+
# style hash, and the Paperclip::Attachment itself. These are set as
|
14
|
+
# instance variables that can be used within `#make`.
|
14
15
|
#
|
15
|
-
#
|
16
|
-
#
|
16
|
+
# #make must return an instance of File (Tempfile is acceptable) which
|
17
|
+
# contains the results of the processing.
|
17
18
|
#
|
18
19
|
# See Paperclip.run for more information about using command-line
|
19
20
|
# utilities from within Processors.
|
@@ -48,7 +48,7 @@ module Paperclip
|
|
48
48
|
end unless defined?(Fog)
|
49
49
|
|
50
50
|
base.instance_eval do
|
51
|
-
unless @options[:url].to_s.match(/\A:fog.*url\
|
51
|
+
unless @options[:url].to_s.match(/\A:fog.*url\z/)
|
52
52
|
@options[:path] = @options[:path].gsub(/:url/, @options[:url]).gsub(/\A:rails_root\/public\/system\//, '')
|
53
53
|
@options[:url] = ':fog_public_url'
|
54
54
|
end
|
@@ -58,7 +58,7 @@ module Paperclip
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX = /\A(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}\
|
61
|
+
AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX = /\A(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}\z))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]\z/
|
62
62
|
|
63
63
|
def exists?(style = default_style)
|
64
64
|
if original_filename
|
data/lib/paperclip/storage/s3.rb
CHANGED
@@ -50,10 +50,9 @@ module Paperclip
|
|
50
50
|
# Or globally:
|
51
51
|
# :s3_permissions => :private
|
52
52
|
#
|
53
|
-
# * +s3_protocol+: The protocol for the URLs generated to your S3 assets.
|
54
|
-
# 'http', 'https', or an empty string to generate
|
55
|
-
#
|
56
|
-
# :s3_permissions are anything else.
|
53
|
+
# * +s3_protocol+: The protocol for the URLs generated to your S3 assets.
|
54
|
+
# Can be either 'http', 'https', or an empty string to generate
|
55
|
+
# protocol-relative URLs. Defaults to empty string.
|
57
56
|
# * +s3_headers+: A hash of headers or a Proc. You may specify a hash such as
|
58
57
|
# {'Expires' => 1.year.from_now.httpdate}. If you use a Proc, headers are determined at
|
59
58
|
# runtime. Paperclip will call that Proc with attachment as the only argument.
|
@@ -99,17 +98,21 @@ module Paperclip
|
|
99
98
|
# "x-amz-meta-" before sending it as a header on the object
|
100
99
|
# upload request. Can be defined both globally and within a style-specific hash.
|
101
100
|
# * +s3_storage_class+: If this option is set to
|
102
|
-
# <tt>:
|
103
|
-
# Redundancy Storage.
|
101
|
+
# <tt>:REDUCED_REDUNDANCY</tt>, the object will be stored using Reduced
|
102
|
+
# Redundancy Storage. RRS enables customers to reduce their
|
104
103
|
# costs by storing non-critical, reproducible data at lower
|
105
104
|
# levels of redundancy than Amazon S3's standard storage.
|
106
105
|
#
|
107
106
|
# You can set storage class on a per style bases by doing the following:
|
108
107
|
# :s3_storage_class => {
|
109
|
-
# :thumb => :
|
108
|
+
# :thumb => :REDUCED_REDUNDANCY
|
110
109
|
# }
|
110
|
+
#
|
111
111
|
# Or globally:
|
112
|
-
# :s3_storage_class => :
|
112
|
+
# :s3_storage_class => :REDUCED_REDUNDANCY
|
113
|
+
#
|
114
|
+
# Other storage classes, such as <tt>:STANDARD_IA</tt>, are also available—see the
|
115
|
+
# documentation for the <tt>aws-sdk</tt> gem for the full list.
|
113
116
|
|
114
117
|
module S3
|
115
118
|
def self.extended base
|
@@ -127,12 +130,7 @@ module Paperclip
|
|
127
130
|
base.instance_eval do
|
128
131
|
@s3_options = @options[:s3_options] || {}
|
129
132
|
@s3_permissions = set_permissions(@options[:s3_permissions])
|
130
|
-
@s3_protocol = @options[:s3_protocol]
|
131
|
-
Proc.new do |style, attachment|
|
132
|
-
permission = (@s3_permissions[style.to_s.to_sym] || @s3_permissions[:default])
|
133
|
-
permission = permission.call(attachment, style) if permission.respond_to?(:call)
|
134
|
-
(permission == :"public-read") ? 'http'.freeze : 'https'.freeze
|
135
|
-
end
|
133
|
+
@s3_protocol = @options[:s3_protocol] || "".freeze
|
136
134
|
@s3_metadata = @options[:s3_metadata] || {}
|
137
135
|
@s3_headers = {}
|
138
136
|
merge_s3_headers(@options[:s3_headers], @s3_headers, @s3_metadata)
|
@@ -147,7 +145,7 @@ module Paperclip
|
|
147
145
|
@s3_server_side_encryption = @options[:s3_server_side_encryption]
|
148
146
|
end
|
149
147
|
|
150
|
-
unless @options[:url].to_s.match(/\A:s3.*url\
|
148
|
+
unless @options[:url].to_s.match(/\A:s3.*url\z/) || @options[:url] == ":asset_host".freeze
|
151
149
|
@options[:path] = path_option.gsub(/:url/, @options[:url]).sub(/\A:rails_root\/public\/system/, "".freeze)
|
152
150
|
@options[:url] = ":s3_path_url".freeze
|
153
151
|
end
|
@@ -2,29 +2,32 @@ require 'uri'
|
|
2
2
|
|
3
3
|
module Paperclip
|
4
4
|
class UrlGenerator
|
5
|
-
def initialize(attachment
|
5
|
+
def initialize(attachment)
|
6
6
|
@attachment = attachment
|
7
|
-
@attachment_options = attachment_options
|
8
7
|
end
|
9
8
|
|
10
9
|
def for(style_name, options)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
interpolated = attachment_options[:interpolator].interpolate(
|
11
|
+
most_appropriate_url, @attachment, style_name
|
12
|
+
)
|
13
|
+
|
14
|
+
escaped = escape_url_as_needed(interpolated, options)
|
15
|
+
timestamp_as_needed(escaped, options)
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
+
attr_reader :attachment
|
21
|
+
delegate :options, to: :attachment, prefix: true
|
22
|
+
|
20
23
|
# This method is all over the place.
|
21
24
|
def default_url
|
22
|
-
if
|
23
|
-
|
24
|
-
elsif
|
25
|
-
@attachment.instance.send(
|
25
|
+
if attachment_options[:default_url].respond_to?(:call)
|
26
|
+
attachment_options[:default_url].call(@attachment)
|
27
|
+
elsif attachment_options[:default_url].is_a?(Symbol)
|
28
|
+
@attachment.instance.send(attachment_options[:default_url])
|
26
29
|
else
|
27
|
-
|
30
|
+
attachment_options[:default_url]
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
@@ -32,7 +35,7 @@ module Paperclip
|
|
32
35
|
if @attachment.original_filename.nil?
|
33
36
|
default_url
|
34
37
|
else
|
35
|
-
|
38
|
+
attachment_options[:url]
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
data/lib/paperclip/validators.rb
CHANGED
@@ -36,7 +36,7 @@ module Paperclip
|
|
36
36
|
options = attributes.extract_options!.dup
|
37
37
|
|
38
38
|
Paperclip::Validators.constants.each do |constant|
|
39
|
-
if constant.to_s =~ /\AAttachment(.+)Validator\
|
39
|
+
if constant.to_s =~ /\AAttachment(.+)Validator\z/
|
40
40
|
validator_kind = $1.underscore.to_sym
|
41
41
|
|
42
42
|
if options.has_key?(validator_kind)
|
data/lib/paperclip/version.rb
CHANGED
@@ -34,7 +34,7 @@ describe Paperclip::AbstractAdapter do
|
|
34
34
|
@adapter.tempfile = stub("Tempfile")
|
35
35
|
end
|
36
36
|
|
37
|
-
[:binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :rewind, :unlink].each do |method|
|
37
|
+
[:binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink].each do |method|
|
38
38
|
it "delegates #{method} to @tempfile" do
|
39
39
|
@adapter.tempfile.stubs(method)
|
40
40
|
@adapter.public_send(method)
|
@@ -1,11 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Paperclip::HttpUrlProxyAdapter do
|
4
|
+
before do
|
5
|
+
@open_return = StringIO.new("xxx")
|
6
|
+
@open_return.stubs(:content_type).returns("image/png")
|
7
|
+
@open_return.stubs(:meta).returns({})
|
8
|
+
Paperclip::HttpUrlProxyAdapter.any_instance.
|
9
|
+
stubs(:download_content).returns(@open_return)
|
10
|
+
end
|
11
|
+
|
4
12
|
context "a new instance" do
|
5
13
|
before do
|
6
|
-
@open_return = StringIO.new("xxx")
|
7
|
-
@open_return.stubs(:content_type).returns("image/png")
|
8
|
-
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).returns(@open_return)
|
9
14
|
@url = "http://thoughtbot.com/images/thoughtbot-logo.png"
|
10
15
|
@subject = Paperclip.io_adapters.for(@url)
|
11
16
|
end
|
@@ -60,7 +65,6 @@ describe Paperclip::HttpUrlProxyAdapter do
|
|
60
65
|
|
61
66
|
context "a url with query params" do
|
62
67
|
before do
|
63
|
-
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).returns(StringIO.new("x"))
|
64
68
|
@url = "https://github.com/thoughtbot/paperclip?file=test"
|
65
69
|
@subject = Paperclip.io_adapters.for(@url)
|
66
70
|
end
|
@@ -76,7 +80,6 @@ describe Paperclip::HttpUrlProxyAdapter do
|
|
76
80
|
|
77
81
|
context "a url with restricted characters in the filename" do
|
78
82
|
before do
|
79
|
-
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).returns(StringIO.new("x"))
|
80
83
|
@url = "https://github.com/thoughtbot/paper:clip.jpg"
|
81
84
|
@subject = Paperclip.io_adapters.for(@url)
|
82
85
|
end
|
@@ -101,7 +104,7 @@ describe Paperclip::HttpUrlProxyAdapter do
|
|
101
104
|
context "a url with special characters in the filename" do
|
102
105
|
it "returns a encoded filename" do
|
103
106
|
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).
|
104
|
-
returns(
|
107
|
+
returns(@open_return)
|
105
108
|
url = "https://github.com/thoughtbot/paperclip-öäü字´½♥زÈ.png"
|
106
109
|
subject = Paperclip.io_adapters.for(url)
|
107
110
|
filename = "paperclip-%C3%B6%C3%A4%C3%BC%E5%AD%97%C2%B4%C2%BD%E2%99%A5"\
|
@@ -29,7 +29,7 @@ describe Paperclip::UploadedFileAdapter do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it "gets the content type" do
|
32
|
-
assert_equal "image/
|
32
|
+
assert_equal "image/png", @subject.content_type
|
33
33
|
end
|
34
34
|
|
35
35
|
it "gets the file's size" do
|
@@ -98,7 +98,7 @@ describe Paperclip::UploadedFileAdapter do
|
|
98
98
|
end
|
99
99
|
|
100
100
|
it "gets the content type" do
|
101
|
-
assert_equal "image/
|
101
|
+
assert_equal "image/png", @subject.content_type
|
102
102
|
end
|
103
103
|
|
104
104
|
it "gets the file's size" do
|
@@ -1,11 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Paperclip::UriAdapter do
|
4
|
+
let(:content_type) { "image/png" }
|
5
|
+
let(:meta) { {} }
|
6
|
+
|
7
|
+
before do
|
8
|
+
@open_return = StringIO.new("xxx")
|
9
|
+
@open_return.stubs(:content_type).returns(content_type)
|
10
|
+
@open_return.stubs(:meta).returns(meta)
|
11
|
+
end
|
12
|
+
|
4
13
|
context "a new instance" do
|
5
14
|
before do
|
6
|
-
|
7
|
-
|
8
|
-
|
15
|
+
Paperclip::UriAdapter.any_instance.
|
16
|
+
stubs(:download_content).returns(@open_return)
|
17
|
+
|
9
18
|
@uri = URI.parse("http://thoughtbot.com/images/thoughtbot-logo.png")
|
10
19
|
@subject = Paperclip.io_adapters.for(@uri)
|
11
20
|
end
|
@@ -56,8 +65,12 @@ describe Paperclip::UriAdapter do
|
|
56
65
|
end
|
57
66
|
|
58
67
|
context "a directory index url" do
|
68
|
+
let(:content_type) { "text/html" }
|
69
|
+
|
59
70
|
before do
|
60
|
-
Paperclip::UriAdapter.any_instance.
|
71
|
+
Paperclip::UriAdapter.any_instance.
|
72
|
+
stubs(:download_content).returns(@open_return)
|
73
|
+
|
61
74
|
@uri = URI.parse("http://thoughtbot.com")
|
62
75
|
@subject = Paperclip.io_adapters.for(@uri)
|
63
76
|
end
|
@@ -73,7 +86,9 @@ describe Paperclip::UriAdapter do
|
|
73
86
|
|
74
87
|
context "a url with query params" do
|
75
88
|
before do
|
76
|
-
Paperclip::UriAdapter.any_instance.
|
89
|
+
Paperclip::UriAdapter.any_instance.
|
90
|
+
stubs(:download_content).returns(@open_return)
|
91
|
+
|
77
92
|
@uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
|
78
93
|
@subject = Paperclip.io_adapters.for(@uri)
|
79
94
|
end
|
@@ -83,9 +98,32 @@ describe Paperclip::UriAdapter do
|
|
83
98
|
end
|
84
99
|
end
|
85
100
|
|
101
|
+
context "a url with content disposition headers" do
|
102
|
+
let(:file_name) { "test_document.pdf" }
|
103
|
+
let(:meta) do
|
104
|
+
{
|
105
|
+
"content-disposition" => "attachment; filename=\"#{file_name}\";",
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
before do
|
110
|
+
Paperclip::UriAdapter.any_instance.
|
111
|
+
stubs(:download_content).returns(@open_return)
|
112
|
+
|
113
|
+
@uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
|
114
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns a file name" do
|
118
|
+
assert_equal file_name, @subject.original_filename
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
86
122
|
context "a url with restricted characters in the filename" do
|
87
123
|
before do
|
88
|
-
Paperclip::UriAdapter.any_instance.
|
124
|
+
Paperclip::UriAdapter.any_instance.
|
125
|
+
stubs(:download_content).returns(@open_return)
|
126
|
+
|
89
127
|
@uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
|
90
128
|
@subject = Paperclip.io_adapters.for(@uri)
|
91
129
|
end
|
@@ -101,7 +139,7 @@ describe Paperclip::UriAdapter do
|
|
101
139
|
|
102
140
|
describe "#download_content" do
|
103
141
|
before do
|
104
|
-
Paperclip::UriAdapter.any_instance.stubs(:open).returns(
|
142
|
+
Paperclip::UriAdapter.any_instance.stubs(:open).returns(@open_return)
|
105
143
|
@uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
|
106
144
|
@subject = Paperclip.io_adapters.for(@uri)
|
107
145
|
end
|
@@ -114,7 +114,7 @@ describe Paperclip::Storage::S3 do
|
|
114
114
|
end
|
115
115
|
|
116
116
|
it "returns a url based on an S3 path" do
|
117
|
-
assert_match %r{
|
117
|
+
assert_match %r{^//s3.amazonaws.com/bucket/avatars/data[^\.]}, @dummy.avatar.url
|
118
118
|
end
|
119
119
|
|
120
120
|
it "uses the correct bucket" do
|
@@ -252,7 +252,7 @@ describe Paperclip::Storage::S3 do
|
|
252
252
|
end
|
253
253
|
|
254
254
|
it "returns a url based on an :s3_host_name path" do
|
255
|
-
assert_match %r{
|
255
|
+
assert_match %r{^//s3-ap-northeast-1.amazonaws.com/bucket/avatars/data[^\.]}, @dummy.avatar.url
|
256
256
|
end
|
257
257
|
|
258
258
|
it "uses the S3 bucket with the correct host name" do
|
@@ -278,7 +278,7 @@ describe Paperclip::Storage::S3 do
|
|
278
278
|
|
279
279
|
it "uses s3_host_name as a proc if available" do
|
280
280
|
@dummy.value = "s3.something.com"
|
281
|
-
assert_equal "
|
281
|
+
assert_equal "//s3.something.com/bucket/avatars/data", @dummy.avatar.url(:original, timestamp: false)
|
282
282
|
end
|
283
283
|
end
|
284
284
|
|
@@ -364,6 +364,58 @@ describe Paperclip::Storage::S3 do
|
|
364
364
|
end
|
365
365
|
end
|
366
366
|
|
367
|
+
context "An attachment that uses S3 for storage and has styles" do
|
368
|
+
before do
|
369
|
+
rebuild_model(
|
370
|
+
(aws2_add_region).merge(
|
371
|
+
storage: :s3,
|
372
|
+
styles: { thumb: ["90x90#", :jpg] },
|
373
|
+
bucket: "bucket",
|
374
|
+
s3_credentials: {
|
375
|
+
"access_key_id" => "12345",
|
376
|
+
"secret_access_key" => "54321" }
|
377
|
+
)
|
378
|
+
)
|
379
|
+
|
380
|
+
@file = File.new(fixture_file("5k.png"), "rb")
|
381
|
+
@dummy = Dummy.new
|
382
|
+
@dummy.avatar = @file
|
383
|
+
@dummy.save
|
384
|
+
end
|
385
|
+
|
386
|
+
context "reprocess" do
|
387
|
+
before do
|
388
|
+
@object = stub
|
389
|
+
@dummy.avatar.stubs(:s3_object).with(:original).returns(@object)
|
390
|
+
@dummy.avatar.stubs(:s3_object).with(:thumb).returns(@object)
|
391
|
+
@object.stubs(:get).yields(@file.read)
|
392
|
+
@object.stubs(:exists?).returns(true)
|
393
|
+
end
|
394
|
+
|
395
|
+
it "uploads original" do
|
396
|
+
@object.expects(:upload_file).with(
|
397
|
+
anything,
|
398
|
+
content_type: "image/png",
|
399
|
+
acl: :"public-read").returns(true)
|
400
|
+
@object.expects(:upload_file).with(
|
401
|
+
anything,
|
402
|
+
content_type: "image/jpeg",
|
403
|
+
acl: :"public-read").returns(true)
|
404
|
+
@dummy.avatar.reprocess!
|
405
|
+
end
|
406
|
+
|
407
|
+
it "doesn't upload original" do
|
408
|
+
@object.expects(:upload_file).with(
|
409
|
+
anything,
|
410
|
+
content_type: "image/jpeg",
|
411
|
+
acl: :"public-read").returns(true)
|
412
|
+
@dummy.avatar.reprocess!(:thumb)
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
after { @file.close }
|
417
|
+
end
|
418
|
+
|
367
419
|
context "An attachment that uses S3 for storage and has spaces in file name" do
|
368
420
|
before do
|
369
421
|
rebuild_model(
|
@@ -435,7 +487,7 @@ describe Paperclip::Storage::S3 do
|
|
435
487
|
end
|
436
488
|
|
437
489
|
it "returns a url based on an S3 subdomain" do
|
438
|
-
assert_match %r{
|
490
|
+
assert_match %r{^//bucket.s3.amazonaws.com/avatars/data[^\.]}, @dummy.avatar.url
|
439
491
|
end
|
440
492
|
end
|
441
493
|
|
@@ -458,7 +510,7 @@ describe Paperclip::Storage::S3 do
|
|
458
510
|
end
|
459
511
|
|
460
512
|
it "returns a url based on the host_alias" do
|
461
|
-
assert_match %r{
|
513
|
+
assert_match %r{^//something.something.com/avatars/data[^\.]}, @dummy.avatar.url
|
462
514
|
end
|
463
515
|
end
|
464
516
|
|
@@ -482,8 +534,8 @@ describe Paperclip::Storage::S3 do
|
|
482
534
|
end
|
483
535
|
|
484
536
|
it "returns a url based on the host_alias" do
|
485
|
-
assert_match %r{
|
486
|
-
assert_match %r{
|
537
|
+
assert_match %r{^//cdn1.example.com/avatars/data[^\.]}, @dummy.avatar.url
|
538
|
+
assert_match %r{^//cdn2.example.com/avatars/data[^\.]}, @dummy.avatar.url
|
487
539
|
end
|
488
540
|
|
489
541
|
it "still returns the bucket name" do
|
@@ -737,7 +789,7 @@ describe Paperclip::Storage::S3 do
|
|
737
789
|
it "does not get a bucket to get a URL" do
|
738
790
|
@dummy.avatar.expects(:s3).never
|
739
791
|
@dummy.avatar.expects(:s3_bucket).never
|
740
|
-
assert_match %r{
|
792
|
+
assert_match %r{^//s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
|
741
793
|
end
|
742
794
|
|
743
795
|
it "is rewound after flush_writes" do
|
@@ -1207,7 +1259,7 @@ describe Paperclip::Storage::S3 do
|
|
1207
1259
|
'access_key_id' => "12345",
|
1208
1260
|
'secret_access_key' => "54321"
|
1209
1261
|
},
|
1210
|
-
s3_server_side_encryption:
|
1262
|
+
s3_server_side_encryption: "AES256"
|
1211
1263
|
end
|
1212
1264
|
|
1213
1265
|
context "when assigned" do
|
@@ -1227,7 +1279,7 @@ describe Paperclip::Storage::S3 do
|
|
1227
1279
|
object.expects(:upload_file)
|
1228
1280
|
.with(anything, content_type: "image/png",
|
1229
1281
|
acl: :"public-read",
|
1230
|
-
server_side_encryption:
|
1282
|
+
server_side_encryption: "AES256")
|
1231
1283
|
@dummy.save
|
1232
1284
|
end
|
1233
1285
|
|
@@ -1474,29 +1526,6 @@ describe Paperclip::Storage::S3 do
|
|
1474
1526
|
}
|
1475
1527
|
)
|
1476
1528
|
end
|
1477
|
-
|
1478
|
-
context "when assigned" do
|
1479
|
-
before do
|
1480
|
-
@file = File.new(fixture_file('5k.png'), 'rb')
|
1481
|
-
@dummy = Dummy.new
|
1482
|
-
@dummy.stubs(:private_attachment? => true)
|
1483
|
-
@dummy.avatar = @file
|
1484
|
-
end
|
1485
|
-
|
1486
|
-
after { @file.close }
|
1487
|
-
|
1488
|
-
context "and saved" do
|
1489
|
-
before do
|
1490
|
-
@dummy.save
|
1491
|
-
end
|
1492
|
-
|
1493
|
-
it "succeeds" do
|
1494
|
-
assert @dummy.avatar.url().include? "https://"
|
1495
|
-
assert @dummy.avatar.url(:thumb).include? "http://"
|
1496
|
-
end
|
1497
|
-
end
|
1498
|
-
end
|
1499
|
-
|
1500
1529
|
end
|
1501
1530
|
end
|
1502
1531
|
|
@@ -4,11 +4,10 @@ require 'spec_helper'
|
|
4
4
|
describe Paperclip::UrlGenerator do
|
5
5
|
it "uses the given interpolator" do
|
6
6
|
expected = "the expected result"
|
7
|
-
mock_attachment = MockAttachment.new
|
8
7
|
mock_interpolator = MockInterpolator.new(result: expected)
|
8
|
+
mock_attachment = MockAttachment.new(interpolator: mock_interpolator)
|
9
9
|
|
10
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
11
|
-
{ interpolator: mock_interpolator })
|
10
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
12
11
|
result = url_generator.for(:style_name, {})
|
13
12
|
|
14
13
|
assert_equal expected, result
|
@@ -17,12 +16,12 @@ describe Paperclip::UrlGenerator do
|
|
17
16
|
end
|
18
17
|
|
19
18
|
it "uses the default URL when no file is assigned" do
|
20
|
-
mock_attachment = MockAttachment.new
|
21
19
|
mock_interpolator = MockInterpolator.new
|
22
20
|
default_url = "the default url"
|
23
|
-
options = { interpolator: mock_interpolator, default_url: default_url}
|
21
|
+
options = { interpolator: mock_interpolator, default_url: default_url }
|
22
|
+
mock_attachment = MockAttachment.new(options)
|
24
23
|
|
25
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
24
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
26
25
|
url_generator.for(:style_name, {})
|
27
26
|
|
28
27
|
assert mock_interpolator.has_interpolated_pattern?(default_url),
|
@@ -30,12 +29,12 @@ describe Paperclip::UrlGenerator do
|
|
30
29
|
end
|
31
30
|
|
32
31
|
it "executes the default URL lambda when no file is assigned" do
|
33
|
-
mock_attachment = MockAttachment.new
|
34
32
|
mock_interpolator = MockInterpolator.new
|
35
33
|
default_url = lambda {|attachment| "the #{attachment.class.name} default url" }
|
36
34
|
options = { interpolator: mock_interpolator, default_url: default_url}
|
35
|
+
mock_attachment = MockAttachment.new(options)
|
37
36
|
|
38
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
37
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
39
38
|
url_generator.for(:style_name, {})
|
40
39
|
|
41
40
|
assert mock_interpolator.has_interpolated_pattern?("the MockAttachment default url"),
|
@@ -44,12 +43,16 @@ describe Paperclip::UrlGenerator do
|
|
44
43
|
|
45
44
|
it "executes the method named by the symbol as the default URL when no file is assigned" do
|
46
45
|
mock_model = FakeModel.new
|
47
|
-
mock_attachment = MockAttachment.new(model: mock_model)
|
48
|
-
mock_interpolator = MockInterpolator.new
|
49
46
|
default_url = :to_s
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
mock_interpolator = MockInterpolator.new
|
48
|
+
options = {
|
49
|
+
interpolator: mock_interpolator,
|
50
|
+
default_url: default_url,
|
51
|
+
model: mock_model,
|
52
|
+
}
|
53
|
+
mock_attachment = MockAttachment.new(options)
|
54
|
+
|
55
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
53
56
|
url_generator.for(:style_name, {})
|
54
57
|
|
55
58
|
assert mock_interpolator.has_interpolated_pattern?(mock_model.to_s),
|
@@ -58,10 +61,10 @@ describe Paperclip::UrlGenerator do
|
|
58
61
|
|
59
62
|
it "URL-escapes spaces if asked to" do
|
60
63
|
expected = "the expected result"
|
61
|
-
mock_attachment = MockAttachment.new
|
62
64
|
mock_interpolator = MockInterpolator.new(result: expected)
|
63
65
|
options = { interpolator: mock_interpolator }
|
64
|
-
|
66
|
+
mock_attachment = MockAttachment.new(options)
|
67
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
65
68
|
|
66
69
|
result = url_generator.for(:style_name, {escape: true})
|
67
70
|
|
@@ -74,10 +77,10 @@ describe Paperclip::UrlGenerator do
|
|
74
77
|
"the escaped result"
|
75
78
|
end
|
76
79
|
end.new
|
77
|
-
mock_attachment = MockAttachment.new
|
78
80
|
mock_interpolator = MockInterpolator.new(result: expected)
|
79
81
|
options = { interpolator: mock_interpolator }
|
80
|
-
|
82
|
+
mock_attachment = MockAttachment.new(options)
|
83
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
81
84
|
|
82
85
|
result = url_generator.for(:style_name, {escape: true})
|
83
86
|
|
@@ -86,10 +89,10 @@ describe Paperclip::UrlGenerator do
|
|
86
89
|
|
87
90
|
it "leaves spaces unescaped as asked to" do
|
88
91
|
expected = "the expected result"
|
89
|
-
mock_attachment = MockAttachment.new
|
90
92
|
mock_interpolator = MockInterpolator.new(result: expected)
|
91
93
|
options = { interpolator: mock_interpolator }
|
92
|
-
|
94
|
+
mock_attachment = MockAttachment.new(options)
|
95
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
93
96
|
|
94
97
|
result = url_generator.for(:style_name, {escape: false})
|
95
98
|
|
@@ -98,10 +101,10 @@ describe Paperclip::UrlGenerator do
|
|
98
101
|
|
99
102
|
it "defaults to leaving spaces unescaped" do
|
100
103
|
expected = "the expected result"
|
101
|
-
mock_attachment = MockAttachment.new
|
102
104
|
mock_interpolator = MockInterpolator.new(result: expected)
|
103
105
|
options = { interpolator: mock_interpolator }
|
104
|
-
|
106
|
+
mock_attachment = MockAttachment.new(options)
|
107
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
105
108
|
|
106
109
|
result = url_generator.for(:style_name, {})
|
107
110
|
|
@@ -111,9 +114,9 @@ describe Paperclip::UrlGenerator do
|
|
111
114
|
it "produces URLs without the updated_at value when the object does not respond to updated_at" do
|
112
115
|
expected = "the expected result"
|
113
116
|
mock_interpolator = MockInterpolator.new(result: expected)
|
114
|
-
|
115
|
-
|
116
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
117
|
+
options = { interpolator: mock_interpolator, responds_to_updated_at: false }
|
118
|
+
mock_attachment = MockAttachment.new(options)
|
119
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
117
120
|
|
118
121
|
result = url_generator.for(:style_name, {timestamp: true})
|
119
122
|
|
@@ -123,9 +126,13 @@ describe Paperclip::UrlGenerator do
|
|
123
126
|
it "produces URLs without the updated_at value when the updated_at value is nil" do
|
124
127
|
expected = "the expected result"
|
125
128
|
mock_interpolator = MockInterpolator.new(result: expected)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
+
options = {
|
130
|
+
responds_to_updated_at: true,
|
131
|
+
updated_at: nil,
|
132
|
+
interpolator: mock_interpolator,
|
133
|
+
}
|
134
|
+
mock_attachment = MockAttachment.new(options)
|
135
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
129
136
|
|
130
137
|
result = url_generator.for(:style_name, {timestamp: true})
|
131
138
|
|
@@ -136,9 +143,9 @@ describe Paperclip::UrlGenerator do
|
|
136
143
|
expected = "the expected result"
|
137
144
|
updated_at = 1231231234
|
138
145
|
mock_interpolator = MockInterpolator.new(result: expected)
|
139
|
-
|
140
|
-
|
141
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
146
|
+
options = { interpolator: mock_interpolator, updated_at: updated_at }
|
147
|
+
mock_attachment = MockAttachment.new(options)
|
148
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
142
149
|
|
143
150
|
result = url_generator.for(:style_name, {timestamp: true})
|
144
151
|
|
@@ -149,9 +156,9 @@ describe Paperclip::UrlGenerator do
|
|
149
156
|
expected = "the?expected=result"
|
150
157
|
updated_at = 1231231234
|
151
158
|
mock_interpolator = MockInterpolator.new(result: expected)
|
152
|
-
|
153
|
-
|
154
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
159
|
+
options = { interpolator: mock_interpolator, updated_at: updated_at }
|
160
|
+
mock_attachment = MockAttachment.new(options)
|
161
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
155
162
|
|
156
163
|
result = url_generator.for(:style_name, {timestamp: true})
|
157
164
|
|
@@ -162,9 +169,9 @@ describe Paperclip::UrlGenerator do
|
|
162
169
|
expected = "the expected result"
|
163
170
|
updated_at = 1231231234
|
164
171
|
mock_interpolator = MockInterpolator.new(result: expected)
|
165
|
-
|
166
|
-
|
167
|
-
url_generator = Paperclip::UrlGenerator.new(mock_attachment
|
172
|
+
options = { interpolator: mock_interpolator, updated_at: updated_at }
|
173
|
+
mock_attachment = MockAttachment.new(options)
|
174
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
168
175
|
|
169
176
|
result = url_generator.for(:style_name, {timestamp: false})
|
170
177
|
|
@@ -173,11 +180,15 @@ describe Paperclip::UrlGenerator do
|
|
173
180
|
|
174
181
|
it "produces the correct URL when the instance has a file name" do
|
175
182
|
expected = "the expected result"
|
176
|
-
mock_attachment = MockAttachment.new(original_filename: 'exists')
|
177
183
|
mock_interpolator = MockInterpolator.new
|
178
|
-
options = {
|
179
|
-
|
180
|
-
|
184
|
+
options = {
|
185
|
+
interpolator: mock_interpolator,
|
186
|
+
url: expected,
|
187
|
+
original_filename: "exists",
|
188
|
+
}
|
189
|
+
mock_attachment = MockAttachment.new(options)
|
190
|
+
|
191
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
181
192
|
url_generator.for(:style_name, {})
|
182
193
|
|
183
194
|
assert mock_interpolator.has_interpolated_pattern?(expected),
|
@@ -186,10 +197,10 @@ describe Paperclip::UrlGenerator do
|
|
186
197
|
|
187
198
|
describe "should be able to escape (, ), [, and ]." do
|
188
199
|
def generate(expected, updated_at=nil)
|
189
|
-
mock_attachment = MockAttachment.new(updated_at: updated_at)
|
190
200
|
mock_interpolator = MockInterpolator.new(result: expected)
|
191
|
-
options = { interpolator: mock_interpolator }
|
192
|
-
|
201
|
+
options = { interpolator: mock_interpolator, updated_at: updated_at }
|
202
|
+
mock_attachment = MockAttachment.new(options)
|
203
|
+
url_generator = Paperclip::UrlGenerator.new(mock_attachment)
|
193
204
|
def url_generator.respond_to(params)
|
194
205
|
false if params == :escape
|
195
206
|
end
|
@@ -31,8 +31,8 @@ describe Paperclip::Validators do
|
|
31
31
|
before do
|
32
32
|
rebuild_class
|
33
33
|
Dummy.validates_attachment :avatar, file_type_ignorance: true, file_name: [
|
34
|
-
{ matches: /\A.*\.jpe?g\
|
35
|
-
{ matches: /\A.{,8}\..+\
|
34
|
+
{ matches: /\A.*\.jpe?g\z/i, message: :invalid_extension },
|
35
|
+
{ matches: /\A.{,8}\..+\z/i, message: [:too_long, count: 8] },
|
36
36
|
]
|
37
37
|
end
|
38
38
|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
class MockAttachment
|
2
2
|
attr_accessor :updated_at, :original_filename
|
3
|
+
attr_reader :options
|
3
4
|
|
4
5
|
def initialize(options = {})
|
6
|
+
@options = options
|
5
7
|
@model = options[:model]
|
6
8
|
@responds_to_updated_at = options[:responds_to_updated_at]
|
7
9
|
@updated_at = options[:updated_at]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paperclip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Yurek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -612,7 +612,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
612
612
|
requirements:
|
613
613
|
- ImageMagick
|
614
614
|
rubyforge_project:
|
615
|
-
rubygems_version: 2.
|
615
|
+
rubygems_version: 2.5.1
|
616
616
|
signing_key:
|
617
617
|
specification_version: 4
|
618
618
|
summary: File attachments as attributes for ActiveRecord
|