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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4787def2cfada09ed3791a17a356d403c289df8a
4
- data.tar.gz: fa4e3a08de8f08483299905ea9ed65e9246bcf9f
3
+ metadata.gz: 70e53f15c9fc9e1ffd3097f25a2fd58de617aa80
4
+ data.tar.gz: 5c2d008914407061d105a5b18d97e9c4e0c88c74
5
5
  SHA512:
6
- metadata.gz: 6c34f90ee3cce719d4915eab1703bb0825584e2361230402bc705e6d5ac0e98e5cc5dc524380d5bed415c38e208604156223f3315044b76ef98b11ddd8cb1817
7
- data.tar.gz: b1b9a56925bb9d9c35725a500f241deab6631c9b1142815dfd1d93104a99de12aa74ae68f4a415599fb3f966ce1b189577e977a1c2d24d521b5f35e592cc76ae
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\/.*\Z/
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\Z/, /jpe?g\Z/]
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." However, you can do much more than just
605
- thumbnail images. By defining a subclass of Paperclip::Processor, you can
606
- perform any processing you want on the files that are attached. Any file in
607
- your Rails app's `lib/paperclip` and `lib/paperclip_processors` directories is
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 :scan, styles: { text: { quality: :better } },
614
- processors: [:ocr]
621
+ has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }
615
622
  ```
616
623
 
617
- This would load the hypothetical class Paperclip::Ocr, which would have the
618
- hash "{ quality: :better }" passed to it along with the uploaded file. For
619
- more information about defining processors, see
620
- [Paperclip::Processor](https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb).
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
- The default processor is Paperclip::Thumbnail. For backward compatibility
623
- reasons, you can pass a single geometry string or an array containing a
624
- geometry and a format that the file will be converted to, like so:
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 :avatar, styles: { thumb: ["32x32#", :png] }
645
+ has_attached_file :scan, styles: { text: { quality: :better } },
646
+ processors: [:ocr]
628
647
  ```
629
648
 
630
- This will convert the "thumb" style to a 32x32 square in PNG format, regardless
631
- of what was uploaded. If the format is not specified, it is kept the same (i.e.
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 will
637
- be given the result of the previous processor's execution. All processors will
638
- receive the same parameters, which are defined in the `:styles` hash.
639
- For example, assuming we had this definition:
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
- then both the :rotator processor and the :ocr processor would receive the
647
- options `{ quality: :better }`. This parameter may not mean anything to one
648
- or more or the processors, and they are expected to ignore it.
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) gem.
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) gem.
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: "true",
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 "http://s3.amazonaws.com/paperclip/attachments/original/5k.png"
81
- And the file at "http://s3.amazonaws.com/paperclip/attachments/original/5k.png" should be uploaded to S3
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
@@ -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, @options)
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{/([^/]*)\Z}.match(attachment.content_type)[1]
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
@@ -24,7 +24,7 @@ module Paperclip
24
24
  end
25
25
 
26
26
  def content_type_detector
27
- self.class.content_type_detector
27
+ self.class.content_type_detector || Paperclip::ContentTypeDetector
28
28
  end
29
29
 
30
30
  def determine_content_type
@@ -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 download_content
17
- options = { read_timeout: Paperclip.options[:read_timeout] }.compact
16
+ def cache_current_values
17
+ self.content_type = content_type_from_content || "text/html"
18
18
 
19
- open(@target, **options)
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 cache_current_values
23
- @original_filename = @target.path.split("/").last
24
- @original_filename ||= "index.html"
25
- self.original_filename = @original_filename.strip
24
+ def content_type_from_content
25
+ if @content.respond_to?(:content_type)
26
+ @content.content_type
27
+ end
28
+ end
26
29
 
27
- @content_type = @content.content_type if @content.respond_to?(:content_type)
28
- @content_type ||= "text/html"
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
- @size = @content.size
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)
@@ -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. Both methods accept 3
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
- # All #make needs to return is an instance of File (Tempfile is
16
- # acceptable) which contains the results of the processing.
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\Z/)
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}\Z))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]\Z/
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
@@ -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. Can be either
54
- # 'http', 'https', or an empty string to generate protocol-relative URLs. Defaults to 'http'
55
- # when your :s3_permissions are :public_read (the default), and 'https' when your
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>:reduced_redundancy</tt>, the object will be stored using Reduced
103
- # Redundancy Storage. RRS enables customers to reduce their
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 => :reduced_reduncancy
108
+ # :thumb => :REDUCED_REDUNDANCY
110
109
  # }
110
+ #
111
111
  # Or globally:
112
- # :s3_storage_class => :reduced_redundancy
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\Z/) || @options[:url] == ":asset_host".freeze
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, attachment_options)
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
- timestamp_as_needed(
12
- escape_url_as_needed(
13
- @attachment_options[:interpolator].interpolate(most_appropriate_url, @attachment, style_name),
14
- options
15
- ), options)
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 @attachment_options[:default_url].respond_to?(:call)
23
- @attachment_options[:default_url].call(@attachment)
24
- elsif @attachment_options[:default_url].is_a?(Symbol)
25
- @attachment.instance.send(@attachment_options[:default_url])
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
- @attachment_options[:default_url]
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
- @attachment_options[:url]
38
+ attachment_options[:url]
36
39
  end
37
40
  end
38
41
 
@@ -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\Z/
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)
@@ -1,5 +1,5 @@
1
1
  module Paperclip
2
2
  unless defined?(Paperclip::VERSION)
3
- VERSION = "5.0.0".freeze
3
+ VERSION = "5.1.0".freeze
4
4
  end
5
5
  end
@@ -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(StringIO.new("x"))
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/x-png-by-browser", @subject.content_type
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/x-png-by-browser", @subject.content_type
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
- @open_return = StringIO.new("xxx")
7
- @open_return.stubs(:content_type).returns("image/png")
8
- Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(@open_return)
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.stubs(:download_content).returns(StringIO.new("xxx"))
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.stubs(:download_content).returns(StringIO.new("xxx"))
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.stubs(:download_content).returns(StringIO.new("xxx"))
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(StringIO.new("xxx"))
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{^http://s3.amazonaws.com/bucket/avatars/data[^\.]}, @dummy.avatar.url
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{^http://s3-ap-northeast-1.amazonaws.com/bucket/avatars/data[^\.]}, @dummy.avatar.url
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 "http://s3.something.com/bucket/avatars/data", @dummy.avatar.url(:original, timestamp: false)
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{^http://bucket.s3.amazonaws.com/avatars/data[^\.]}, @dummy.avatar.url
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{^http://something.something.com/avatars/data[^\.]}, @dummy.avatar.url
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{^http://cdn1.example.com/avatars/data[^\.]}, @dummy.avatar.url
486
- assert_match %r{^http://cdn2.example.com/avatars/data[^\.]}, @dummy.avatar.url
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{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
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: :aes256
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: :aes256)
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, options)
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, options)
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
- options = { interpolator: mock_interpolator, default_url: default_url}
51
-
52
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- mock_attachment = MockAttachment.new(responds_to_updated_at: false)
115
- options = { interpolator: mock_interpolator }
116
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- mock_attachment = MockAttachment.new(responds_to_updated_at: true, updated_at: nil)
127
- options = { interpolator: mock_interpolator }
128
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- mock_attachment = MockAttachment.new(updated_at: updated_at)
140
- options = { interpolator: mock_interpolator }
141
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- mock_attachment = MockAttachment.new(updated_at: updated_at)
153
- options = { interpolator: mock_interpolator }
154
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- mock_attachment = MockAttachment.new(updated_at: updated_at)
166
- options = { interpolator: mock_interpolator }
167
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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 = { interpolator: mock_interpolator, url: expected}
179
-
180
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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
- url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
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\Z/i, message: :invalid_extension },
35
- { matches: /\A.{,8}\..+\Z/i, message: [:too_long, count: 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]
@@ -2,9 +2,9 @@ class MockUrlGeneratorBuilder
2
2
  def initializer
3
3
  end
4
4
 
5
- def new(attachment, attachment_options)
5
+ def new(attachment)
6
6
  @attachment = attachment
7
- @attachment_options = attachment_options
7
+ @attachment_options = @attachment.options
8
8
  self
9
9
  end
10
10
 
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.0.0
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-07-01 00:00:00.000000000 Z
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.6.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