paperclip 3.5.2 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +17 -0
  3. data/.gitignore +0 -6
  4. data/.hound.yml +1055 -0
  5. data/.rubocop.yml +1 -0
  6. data/.travis.yml +19 -13
  7. data/Appraisals +4 -16
  8. data/CONTRIBUTING.md +29 -13
  9. data/Gemfile +10 -7
  10. data/LICENSE +1 -3
  11. data/NEWS +226 -23
  12. data/README.md +494 -152
  13. data/RELEASING.md +17 -0
  14. data/Rakefile +6 -8
  15. data/UPGRADING +12 -9
  16. data/features/basic_integration.feature +27 -8
  17. data/features/migration.feature +0 -24
  18. data/features/step_definitions/attachment_steps.rb +36 -28
  19. data/features/step_definitions/html_steps.rb +2 -2
  20. data/features/step_definitions/rails_steps.rb +68 -37
  21. data/features/step_definitions/s3_steps.rb +2 -2
  22. data/features/step_definitions/web_steps.rb +1 -103
  23. data/features/support/env.rb +3 -2
  24. data/features/support/file_helpers.rb +2 -2
  25. data/features/support/fixtures/gemfile.txt +1 -1
  26. data/features/support/paths.rb +1 -1
  27. data/features/support/rails.rb +2 -25
  28. data/gemfiles/4.2.gemfile +17 -0
  29. data/gemfiles/5.0.gemfile +17 -0
  30. data/lib/generators/paperclip/paperclip_generator.rb +0 -2
  31. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
  32. data/lib/paperclip/attachment.rb +160 -47
  33. data/lib/paperclip/attachment_registry.rb +4 -1
  34. data/lib/paperclip/callbacks.rb +13 -1
  35. data/lib/paperclip/content_type_detector.rb +26 -24
  36. data/lib/paperclip/errors.rb +8 -1
  37. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  38. data/lib/paperclip/geometry_detector_factory.rb +10 -3
  39. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  40. data/lib/paperclip/glue.rb +1 -1
  41. data/lib/paperclip/has_attached_file.rb +17 -1
  42. data/lib/paperclip/helpers.rb +14 -10
  43. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  44. data/lib/paperclip/interpolations.rb +27 -14
  45. data/lib/paperclip/io_adapters/abstract_adapter.rb +28 -4
  46. data/lib/paperclip/io_adapters/attachment_adapter.rb +13 -8
  47. data/lib/paperclip/io_adapters/data_uri_adapter.rb +11 -16
  48. data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
  49. data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
  50. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +8 -8
  51. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
  52. data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
  53. data/lib/paperclip/io_adapters/registry.rb +6 -2
  54. data/lib/paperclip/io_adapters/stringio_adapter.rb +15 -16
  55. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
  56. data/lib/paperclip/io_adapters/uri_adapter.rb +41 -19
  57. data/lib/paperclip/locales/en.yml +1 -0
  58. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
  59. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  60. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
  61. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  62. data/lib/paperclip/media_type_spoof_detector.rb +89 -0
  63. data/lib/paperclip/processor.rb +5 -41
  64. data/lib/paperclip/processor_helpers.rb +50 -0
  65. data/lib/paperclip/rails_environment.rb +25 -0
  66. data/lib/paperclip/schema.rb +9 -7
  67. data/lib/paperclip/storage/filesystem.rb +14 -3
  68. data/lib/paperclip/storage/fog.rb +47 -22
  69. data/lib/paperclip/storage/s3.rb +144 -73
  70. data/lib/paperclip/style.rb +8 -2
  71. data/lib/paperclip/tempfile_factory.rb +6 -4
  72. data/lib/paperclip/thumbnail.rb +26 -14
  73. data/lib/paperclip/url_generator.rb +25 -14
  74. data/lib/paperclip/validators/attachment_content_type_validator.rb +4 -0
  75. data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
  76. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
  77. data/lib/paperclip/validators/attachment_presence_validator.rb +4 -0
  78. data/lib/paperclip/validators/attachment_size_validator.rb +5 -3
  79. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +27 -0
  80. data/lib/paperclip/validators.rb +12 -3
  81. data/lib/paperclip/version.rb +3 -1
  82. data/lib/paperclip.rb +31 -11
  83. data/lib/tasks/paperclip.rake +34 -5
  84. data/paperclip.gemspec +18 -17
  85. data/shoulda_macros/paperclip.rb +13 -3
  86. data/{test → spec}/database.yml +0 -0
  87. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  88. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +17 -20
  89. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  90. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +524 -400
  91. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +17 -19
  92. data/{test/file_command_content_type_detector_test.rb → spec/paperclip/file_command_content_type_detector_spec.rb} +7 -6
  93. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  94. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  95. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  96. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +50 -52
  97. data/spec/paperclip/glue_spec.rb +44 -0
  98. data/spec/paperclip/has_attached_file_spec.rb +158 -0
  99. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +141 -133
  100. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +70 -46
  101. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +101 -0
  102. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +38 -34
  103. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +89 -0
  104. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  105. data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
  106. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +121 -0
  107. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  108. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  109. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +12 -9
  110. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +21 -18
  111. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +46 -46
  112. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +172 -0
  113. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  114. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +109 -0
  115. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  116. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  117. data/spec/paperclip/media_type_spoof_detector_spec.rb +79 -0
  118. data/spec/paperclip/meta_class_spec.rb +30 -0
  119. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  120. data/{test/paperclip_test.rb → spec/paperclip/paperclip_spec.rb} +46 -71
  121. data/spec/paperclip/plural_cache_spec.rb +37 -0
  122. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  123. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +5 -5
  124. data/spec/paperclip/rails_environment_spec.rb +33 -0
  125. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  126. data/spec/paperclip/schema_spec.rb +248 -0
  127. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  128. data/spec/paperclip/storage/fog_spec.rb +561 -0
  129. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  130. data/spec/paperclip/storage/s3_spec.rb +1693 -0
  131. data/spec/paperclip/style_spec.rb +255 -0
  132. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  133. data/spec/paperclip/tempfile_spec.rb +35 -0
  134. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +150 -131
  135. data/spec/paperclip/url_generator_spec.rb +222 -0
  136. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  137. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  138. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +20 -20
  139. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +77 -64
  140. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  141. data/spec/paperclip/validators_spec.rb +164 -0
  142. data/spec/spec_helper.rb +47 -0
  143. data/spec/support/assertions.rb +82 -0
  144. data/spec/support/conditional_filter_helper.rb +5 -0
  145. data/spec/support/fake_model.rb +25 -0
  146. data/spec/support/fake_rails.rb +12 -0
  147. data/{test → spec/support}/fixtures/12k.png +0 -0
  148. data/{test → spec/support}/fixtures/50x50.png +0 -0
  149. data/{test → spec/support}/fixtures/5k.png +0 -0
  150. data/{test → spec/support}/fixtures/animated +0 -0
  151. data/{test → spec/support}/fixtures/animated.gif +0 -0
  152. data/{test → spec/support}/fixtures/animated.unknown +0 -0
  153. data/{test → spec/support}/fixtures/bad.png +0 -0
  154. data/spec/support/fixtures/empty.html +1 -0
  155. data/spec/support/fixtures/empty.xlsx +0 -0
  156. data/{test → spec/support}/fixtures/fog.yml +0 -0
  157. data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  158. data/{test → spec/support}/fixtures/s3.yml +0 -0
  159. data/spec/support/fixtures/spaced file.jpg +0 -0
  160. data/{test → spec/support}/fixtures/spaced file.png +0 -0
  161. data/{test → spec/support}/fixtures/text.txt +0 -0
  162. data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  163. data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  164. data/spec/support/matchers/accept.rb +5 -0
  165. data/spec/support/matchers/exist.rb +5 -0
  166. data/spec/support/matchers/have_column.rb +23 -0
  167. data/{test → spec}/support/mock_attachment.rb +2 -0
  168. data/{test → spec}/support/mock_interpolator.rb +0 -0
  169. data/{test → spec}/support/mock_url_generator_builder.rb +2 -2
  170. data/spec/support/model_reconstruction.rb +68 -0
  171. data/spec/support/reporting.rb +11 -0
  172. data/spec/support/test_data.rb +13 -0
  173. data/spec/support/version_helper.rb +9 -0
  174. metadata +262 -297
  175. data/RUNNING_TESTS.md +0 -4
  176. data/cucumber/paperclip_steps.rb +0 -6
  177. data/gemfiles/3.0.gemfile +0 -11
  178. data/gemfiles/3.1.gemfile +0 -11
  179. data/gemfiles/3.2.gemfile +0 -11
  180. data/gemfiles/4.0.gemfile +0 -11
  181. data/test/attachment_definitions_test.rb +0 -12
  182. data/test/attachment_registry_test.rb +0 -77
  183. data/test/filename_cleaner_test.rb +0 -14
  184. data/test/generator_test.rb +0 -80
  185. data/test/geometry_detector_test.rb +0 -24
  186. data/test/has_attached_file_test.rb +0 -125
  187. data/test/helper.rb +0 -215
  188. data/test/io_adapters/abstract_adapter_test.rb +0 -58
  189. data/test/io_adapters/data_uri_adapter_test.rb +0 -67
  190. data/test/io_adapters/empty_string_adapter_test.rb +0 -17
  191. data/test/io_adapters/file_adapter_test.rb +0 -119
  192. data/test/io_adapters/http_url_proxy_adapter_test.rb +0 -102
  193. data/test/io_adapters/identity_adapter_test.rb +0 -8
  194. data/test/io_adapters/uri_adapter_test.rb +0 -102
  195. data/test/matchers/have_attached_file_matcher_test.rb +0 -24
  196. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -110
  197. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -69
  198. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -86
  199. data/test/meta_class_test.rb +0 -32
  200. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  201. data/test/plural_cache_test.rb +0 -36
  202. data/test/schema_test.rb +0 -200
  203. data/test/storage/fog_test.rb +0 -453
  204. data/test/storage/s3_live_test.rb +0 -179
  205. data/test/storage/s3_test.rb +0 -1348
  206. data/test/style_test.rb +0 -213
  207. data/test/support/mock_model.rb +0 -2
  208. data/test/tempfile_factory_test.rb +0 -13
  209. data/test/url_generator_test.rb +0 -187
  210. data/test/validators/attachment_content_type_validator_test.rb +0 -323
  211. data/test/validators_test.rb +0 -32
data/README.md CHANGED
@@ -1,9 +1,68 @@
1
1
  Paperclip
2
2
  =========
3
3
 
4
- [![Build Status](https://secure.travis-ci.org/thoughtbot/paperclip.png?branch=master)](http://travis-ci.org/thoughtbot/paperclip) [![Dependency Status](https://gemnasium.com/thoughtbot/paperclip.png?travis)](https://gemnasium.com/thoughtbot/paperclip) [![Code Climate](https://codeclimate.com/github/thoughtbot/paperclip.png)](https://codeclimate.com/github/thoughtbot/paperclip)
4
+ ## Documentation valid for `master` branch
5
5
 
6
- Paperclip is intended as an easy file attachment library for Active Record. The
6
+ Please check the documentation for the paperclip version you are using:
7
+ https://github.com/thoughtbot/paperclip/releases
8
+
9
+ ---
10
+
11
+ [![Build Status](https://secure.travis-ci.org/thoughtbot/paperclip.svg?branch=master)](http://travis-ci.org/thoughtbot/paperclip)
12
+ [![Dependency Status](https://gemnasium.com/thoughtbot/paperclip.svg?travis)](https://gemnasium.com/thoughtbot/paperclip)
13
+ [![Code Climate](https://codeclimate.com/github/thoughtbot/paperclip.svg)](https://codeclimate.com/github/thoughtbot/paperclip)
14
+ [![Inline docs](http://inch-ci.org/github/thoughtbot/paperclip.svg)](http://inch-ci.org/github/thoughtbot/paperclip)
15
+ [![Security](https://hakiri.io/github/thoughtbot/paperclip/master.svg)](https://hakiri.io/github/thoughtbot/paperclip/master)
16
+
17
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
18
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
19
+
20
+ - [Requirements](#requirements)
21
+ - [Ruby and Rails](#ruby-and-rails)
22
+ - [Image Processor](#image-processor)
23
+ - [`file`](#file)
24
+ - [Installation](#installation)
25
+ - [Quick Start](#quick-start)
26
+ - [Models](#models)
27
+ - [Migrations](#migrations)
28
+ - [Edit and New Views](#edit-and-new-views)
29
+ - [Edit and New Views with Simple Form](#edit-and-new-views-with-simple-form)
30
+ - [Controller](#controller)
31
+ - [View Helpers](#view-helpers)
32
+ - [Checking a File Exists](#checking-a-file-exists)
33
+ - [Deleting an Attachment](#deleting-an-attachment)
34
+ - [Usage](#usage)
35
+ - [Validations](#validations)
36
+ - [Internationalization (I18n)](#internationalization-i18n)
37
+ - [Security Validations](#security-validations)
38
+ - [Defaults](#defaults)
39
+ - [Migrations](#migrations-1)
40
+ - [Add Attachment Column To A Table](#add-attachment-column-to-a-table)
41
+ - [Schema Definition](#schema-definition)
42
+ - [Vintage Syntax](#vintage-syntax)
43
+ - [Storage](#storage)
44
+ - [Understanding Storage](#understanding-storage)
45
+ - [IO Adapters](#io-adapters)
46
+ - [Post Processing](#post-processing)
47
+ - [Custom Attachment Processors](#custom-attachment-processors)
48
+ - [Events](#events)
49
+ - [URI Obfuscation](#uri-obfuscation)
50
+ - [Checksum / Fingerprint](#checksum--fingerprint)
51
+ - [File Preservation for Soft-Delete](#file-preservation-for-soft-delete)
52
+ - [Dynamic Configuration](#dynamic-configuration)
53
+ - [Dynamic Styles:](#dynamic-styles)
54
+ - [Dynamic Processors:](#dynamic-processors)
55
+ - [Logging](#logging)
56
+ - [Deployment](#deployment)
57
+ - [Attachment Styles](#attachment-styles)
58
+ - [Testing](#testing)
59
+ - [Contributing](#contributing)
60
+ - [License](#license)
61
+ - [About thoughtbot](#about-thoughtbot)
62
+
63
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
64
+
65
+ Paperclip is intended as an easy file attachment library for ActiveRecord. The
7
66
  intent behind it was to keep setup as easy as possible and to treat files as
8
67
  much like other attributes as possible. This means they aren't saved to their
9
68
  final locations on disk, nor are they deleted if set to nil, until
@@ -15,20 +74,20 @@ packages). Attached files are saved to the filesystem and referenced in the
15
74
  browser by an easily understandable specification, which has sensible and
16
75
  useful defaults.
17
76
 
18
- See the documentation for `has_attached_file` in [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods) for
77
+ See the documentation for `has_attached_file` in [`Paperclip::ClassMethods`](http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods) for
19
78
  more detailed options.
20
79
 
21
- The complete [RDoc](http://rdoc.info/gems/paperclip) is online.
80
+ The complete [RDoc](http://www.rubydoc.info/gems/paperclip) is online.
22
81
 
82
+ ---
23
83
 
24
84
  Requirements
25
85
  ------------
26
86
 
27
87
  ### Ruby and Rails
28
88
 
29
- Paperclip now requires Ruby version **>= 1.9.2** and Rails version **>= 3.0** (Only if you're going to use Paperclip with Ruby on Rails.)
30
-
31
- If you're still on Ruby 1.8.7 or Ruby on Rails 2.3.x, you can still use Paperclip 2.7.x with your project. Also, everything in this README might not apply to your version of Paperclip, and you should read [the README for version 2.7](http://rubydoc.info/gems/paperclip/2.7.0) instead.
89
+ Paperclip now requires Ruby version **>= 2.1** and Rails version **>= 4.2**
90
+ (only if you're going to use Paperclip with Ruby on Rails.)
32
91
 
33
92
  ### Image Processor
34
93
 
@@ -46,15 +105,59 @@ In development mode, you might add this line to `config/environments/development
46
105
  Paperclip.options[:command_path] = "/usr/local/bin/"
47
106
  ```
48
107
 
49
- If you're on Mac OS X, you'll want to run the following with Homebrew:
108
+ If you're on Mac OS X, you'll want to run the following with [Homebrew] (http://www.brew.sh):
50
109
 
51
110
  brew install imagemagick
52
111
 
53
112
  If you are dealing with pdf uploads or running the test suite, you'll also need
54
- GhostScript to be installed. On Mac OS X, you can also install that using Homebrew:
113
+ to install GhostScript. On Mac OS X, you can also install that using Homebrew:
55
114
 
56
115
  brew install gs
57
116
 
117
+ If you are on Ubuntu (or any Debian base Linux distribution), you'll want to run
118
+ the following with apt-get:
119
+
120
+ sudo apt-get install imagemagick -y
121
+
122
+ ### `file`
123
+
124
+ The Unix [`file` command](https://en.wikipedia.org/wiki/File_(command)) is required for content-type checking.
125
+ This utility isn't available in Windows, but comes bundled with Ruby [Devkit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit),
126
+ so Windows users must make sure that the devkit is installed and added to the system `PATH`.
127
+
128
+ **Manual Installation**
129
+
130
+ If you're using Windows 7+ as a development environment, you may need to install the `file.exe` application manually. The `file spoofing` system in Paperclip 4+ relies on this; if you don't have it working, you'll receive `Validation failed: Upload file has an extension that does not match its contents.` errors.
131
+
132
+ To manually install, you should perform the following:
133
+
134
+ > **Download & install `file` from [this URL](http://gnuwin32.sourceforge.net/packages/file.htm)**
135
+
136
+ To test, you can use the image below:
137
+ ![untitled](https://cloud.githubusercontent.com/assets/1104431/4524452/a1f8cce4-4d44-11e4-872e-17adb96f79c9.png)
138
+
139
+ Next, you need to integrate with your environment - preferably through the `PATH` variable, or by changing your `config/environments/development.rb` file
140
+
141
+ **PATH**
142
+
143
+ 1. Click "Start"
144
+ 2. On "Computer", right-click and select "Properties"
145
+ 3. In Properties, select "Advanced System Settings"
146
+ 4. Click the "Environment Variables" button
147
+ 5. Locate the "PATH" var - at the end, add the path to your newly installed `file.exe` (typically `C:\Program Files (x86)\GnuWin32\bin`)
148
+ 6. Restart any CMD shells you have open & see if it works
149
+
150
+ OR
151
+
152
+ **Environment**
153
+
154
+ 1. Open `config/environments/development.rb`
155
+ 2. Add the following line: `Paperclip.options[:command_path] = 'C:\Program Files (x86)\GnuWin32\bin'`
156
+ 3. Restart your Rails server
157
+
158
+ Either of these methods will give your Rails setup access to the `file.exe` functionality, thus providing the ability to check the contents of a file (fixing the spoofing problem)
159
+
160
+ ---
58
161
 
59
162
  Installation
60
163
  ------------
@@ -64,80 +167,93 @@ Paperclip is distributed as a gem, which is how it should be used in your app.
64
167
  Include the gem in your Gemfile:
65
168
 
66
169
  ```ruby
67
- gem "paperclip", "~> 3.0"
68
- ```
69
-
70
- If you're still using Rails 2.3.x, you should do this instead:
71
-
72
- ```ruby
73
- gem "paperclip", "~> 2.7"
170
+ gem "paperclip", "~> 5.0.0"
74
171
  ```
75
172
 
76
173
  Or, if you want to get the latest, you can get master from the main paperclip repository:
77
174
 
78
175
  ```ruby
79
- gem "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"
176
+ gem "paperclip", git: "git://github.com/thoughtbot/paperclip.git"
80
177
  ```
81
178
 
82
179
  If you're trying to use features that don't seem to be in the latest released gem, but are
83
180
  mentioned in this README, then you probably need to specify the master branch if you want to
84
- use them. This README is probably ahead of the latest released version, if you're reading it
181
+ use them. This README is probably ahead of the latest released version if you're reading it
85
182
  on GitHub.
86
183
 
87
184
  For Non-Rails usage:
88
185
 
89
186
  ```ruby
90
187
  class ModuleName < ActiveRecord::Base
91
- include Paperclip::Glue
92
- ...
188
+ include Paperclip::Glue
189
+ ...
93
190
  end
94
191
  ```
95
192
 
193
+ ---
194
+
96
195
  Quick Start
97
196
  -----------
98
197
 
99
- In your model:
198
+ ### Models
100
199
 
101
200
  ```ruby
102
201
  class User < ActiveRecord::Base
103
- attr_accessible :avatar
104
- has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
202
+ has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
203
+ validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
105
204
  end
106
205
  ```
107
206
 
108
- In your migrations:
207
+ ### Migrations
109
208
 
110
209
  ```ruby
111
210
  class AddAvatarColumnsToUsers < ActiveRecord::Migration
112
- def self.up
211
+ def up
113
212
  add_attachment :users, :avatar
114
213
  end
115
214
 
116
- def self.down
215
+ def down
117
216
  remove_attachment :users, :avatar
118
217
  end
119
218
  end
120
219
  ```
121
220
 
122
- (Or you can use migration generator: `rails generate paperclip user avatar`)
221
+ (Or you can use the Rails migration generator: `rails generate paperclip user avatar`)
123
222
 
124
- In your edit and new views:
223
+ ### Edit and New Views
125
224
 
126
225
  ```erb
127
- <%= form_for @user, :url => users_path, :html => { :multipart => true } do |form| %>
226
+ <%= form_for @user, url: users_path, html: { multipart: true } do |form| %>
128
227
  <%= form.file_field :avatar %>
129
228
  <% end %>
130
229
  ```
131
230
 
132
- In your controller:
231
+ ### Edit and New Views with [Simple Form](https://github.com/plataformatec/simple_form)
232
+
233
+ ```erb
234
+ <%= simple_form_for @user, url: users_path do |form| %>
235
+ <%= form.input :avatar, as: :file %>
236
+ <% end %>
237
+ ```
238
+
239
+ ### Controller
133
240
 
134
241
  ```ruby
135
242
  def create
136
- @user = User.create( params[:user] )
243
+ @user = User.create( user_params )
244
+ end
245
+
246
+ private
247
+
248
+ # Use strong_parameters for attribute whitelisting
249
+ # Be sure to update your create() and update() controller methods.
250
+
251
+ def user_params
252
+ params.require(:user).permit(:avatar)
137
253
  end
138
254
  ```
139
255
 
140
- In your show view:
256
+ ### View Helpers
141
257
 
142
258
  ```erb
143
259
  <%= image_tag @user.avatar.url %>
@@ -145,20 +261,33 @@ In your show view:
145
261
  <%= image_tag @user.avatar.url(:thumb) %>
146
262
  ```
147
263
 
148
- To detach a file, simply set the attribute to `nil`:
264
+ ### Checking a File Exists
265
+
266
+ There are two methods for checking if a file exists:
267
+
268
+ - `file?` and `present?` checks if the `_file_name` field is populated
269
+ - `exists?` checks if the file exists (will perform a TCP connection if stored in the cloud)
270
+
271
+ Keep this in mind if you are checking if files are present in a loop. The first
272
+ version is significantly more performant, but has different semantics.
273
+
274
+ ### Deleting an Attachment
275
+
276
+ Set the attribute to `nil` and save.
149
277
 
150
278
  ```ruby
151
279
  @user.avatar = nil
152
280
  @user.save
153
281
  ```
282
+ ---
154
283
 
155
284
  Usage
156
285
  -----
157
286
 
158
- The basics of paperclip are quite simple: Declare that your model has an
287
+ The basics of Paperclip are quite simple: Declare that your model has an
159
288
  attachment with the `has_attached_file` method, and give it a name.
160
289
 
161
- Paperclip will wrap up up to four attributes (all prefixed with that attachment's name,
290
+ Paperclip will wrap up to four attributes (all prefixed with that attachment's name,
162
291
  so you can have multiple attachments per model if you wish) and give them a
163
292
  friendly front end. These attributes are:
164
293
 
@@ -167,12 +296,12 @@ friendly front end. These attributes are:
167
296
  * `<attachment>_content_type`
168
297
  * `<attachment>_updated_at`
169
298
 
170
- By default, only `<attachment>_file_name` is required for paperclip to operate.
299
+ By default, only `<attachment>_file_name` is required for Paperclip to operate.
171
300
  You'll need to add `<attachment>_content_type` in case you want to use content type
172
301
  validation.
173
302
 
174
- More information about the options to `has_attached_file` is available in the
175
- documentation of [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
303
+ More information about the options passed to `has_attached_file` is available in the
304
+ documentation of [`Paperclip::ClassMethods`](http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
176
305
 
177
306
  Validations
178
307
  -----------
@@ -186,8 +315,10 @@ For validations, Paperclip introduces several validators to validate your attach
186
315
  Example Usage:
187
316
 
188
317
  ```ruby
189
- validates :avatar, :attachment_presence => true
190
- validates_with AttachmentPresenceValidator, :attributes => :avatar
318
+ validates :avatar, attachment_presence: true
319
+ validates_with AttachmentPresenceValidator, attributes: :avatar
320
+ validates_with AttachmentSizeValidator, attributes: :avatar, less_than: 1.megabytes
321
+
191
322
  ```
192
323
 
193
324
  Validators can also be defined using the old helper style:
@@ -205,13 +336,13 @@ validates_attachment_presence :avatar
205
336
  Lastly, you can also define multiple validations on a single attachment using `validates_attachment`:
206
337
 
207
338
  ```ruby
208
- validates_attachment :avatar, :presence => true,
209
- :content_type => { :content_type => "image/jpg" },
210
- :size => { :in => 0..10.kilobytes }
339
+ validates_attachment :avatar, presence: true,
340
+ content_type: { content_type: "image/jpeg" },
341
+ size: { in: 0..10.kilobytes }
211
342
  ```
212
343
 
213
- _NOTE: Post processing will not even *start* if the attachment is not valid
214
- according to the validations. Your callbacks and processors will *only* be
344
+ _NOTE: Post-processing will not even **start** if the attachment is not valid
345
+ according to the validations. Your callbacks and processors will **only** be
215
346
  called with valid attachments._
216
347
 
217
348
  ```ruby
@@ -253,55 +384,138 @@ class BooksController < ApplicationController
253
384
  end
254
385
  ```
255
386
 
387
+ **A note on content_type validations and security**
388
+
389
+ You should ensure that you validate files to be only those MIME types you
390
+ explicitly want to support. If you don't, you could be open to
391
+ <a href="https://www.owasp.org/index.php/Testing_for_Stored_Cross_site_scripting_(OWASP-DV-002)">XSS attacks</a>
392
+ if a user uploads a file with a malicious HTML payload.
393
+
394
+ If you're only interested in images, restrict your allowed content_types to
395
+ image-y ones:
396
+
397
+ ```ruby
398
+ validates_attachment :avatar,
399
+ content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
400
+ ```
401
+
402
+ `Paperclip::ContentTypeDetector` will attempt to match a file's extension to an
403
+ inferred content_type, regardless of the actual contents of the file.
404
+
405
+ ---
406
+
407
+ Internationalization (I18n)
408
+ ---------------------------
409
+
410
+ For using or adding locale files in different languages, check the project
411
+ https://github.com/thoughtbot/paperclip-i18n.
412
+
413
+ Security Validations
414
+ ====================
415
+
416
+ Thanks to a report from [Egor Homakov](http://homakov.blogspot.com/) we have
417
+ taken steps to prevent people from spoofing Content-Types and getting data
418
+ you weren't expecting onto your server.
419
+
420
+ NOTE: Starting at version 4.0.0, all attachments are *required* to include a
421
+ content_type validation, a file_name validation, or to explicitly state that
422
+ they're not going to have either. *Paperclip will raise an error* if you do not
423
+ do this.
424
+
425
+ ```ruby
426
+ class ActiveRecord::Base
427
+ has_attached_file :avatar
428
+ # Validate content type
429
+ validates_attachment_content_type :avatar, content_type: /\Aimage/
430
+ # Validate filename
431
+ validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
432
+ # Explicitly do not validate
433
+ do_not_validate_attachment_file_type :avatar
434
+ end
435
+ ```
436
+
437
+ This keeps Paperclip secure-by-default, and will prevent people trying to mess
438
+ with your filesystem.
439
+
440
+ NOTE: Also starting at version 4.0.0, Paperclip has another validation that
441
+ cannot be turned off. This validation will prevent content type spoofing. That
442
+ is, uploading a PHP document (for example) as part of the EXIF tags of a
443
+ well-formed JPEG. This check is limited to the media type (the first part of the
444
+ MIME type, so, 'text' in `text/plain`). This will prevent HTML documents from
445
+ being uploaded as JPEGs, but will not prevent GIFs from being uploaded with a
446
+ `.jpg` extension. This validation will only add validation errors to the form. It
447
+ will not cause errors to be raised.
448
+
449
+ This can sometimes cause false validation errors in applications that use custom
450
+ file extensions. In these cases you may wish to add your custom extension to the
451
+ list of content type mappings by creating `config/initializers/paperclip.rb`:
452
+
453
+ ```ruby
454
+ # Allow ".foo" as an extension for files with the MIME type "text/plain".
455
+ Paperclip.options[:content_type_mappings] = {
456
+ foo: %w(text/plain)
457
+ }
458
+ ```
459
+
460
+ ---
461
+
256
462
  Defaults
257
463
  --------
258
- Global defaults for all your paperclip attachments can be defined by changing the Paperclip::Attachment.default_options Hash, this can be useful for setting your default storage settings per example so you won't have to define them in every has_attached_file definition.
464
+ Global defaults for all your Paperclip attachments can be defined by changing the Paperclip::Attachment.default_options Hash. This can be useful for setting your default storage settings per example so you won't have to define them in every `has_attached_file` definition.
259
465
 
260
- If you're using Rails you can define a Hash with default options in config/application.rb or in any of the config/environments/*.rb files on config.paperclip_defaults, these will get merged into Paperclip::Attachment.default_options as your Rails app boots. An example:
466
+ If you're using Rails, you can define a Hash with default options in `config/application.rb` or in any of the `config/environments/*.rb` files on config.paperclip_defaults. These will get merged into `Paperclip::Attachment.default_options` as your Rails app boots. An example:
261
467
 
262
468
  ```ruby
263
469
  module YourApp
264
470
  class Application < Rails::Application
265
471
  # Other code...
266
472
 
267
- config.paperclip_defaults = {:storage => :fog, :fog_credentials => {:provider => "Local", :local_root => "#{Rails.root}/public"}, :fog_directory => "", :fog_host => "localhost"}
473
+ config.paperclip_defaults = { storage: :fog, fog_credentials: { provider: "Local", local_root: "#{Rails.root}/public"}, fog_directory: "", fog_host: "localhost"}
268
474
  end
269
475
  end
270
476
  ```
271
477
 
272
- Another option is to directly modify the Paperclip::Attachment.default_options Hash, this method works for non-Rails applications or is an option if you prefer to place the Paperclip default settings in an initializer.
478
+ Another option is to directly modify the `Paperclip::Attachment.default_options` Hash - this method works for non-Rails applications or is an option if you prefer to place the Paperclip default settings in an initializer.
273
479
 
274
480
  An example Rails initializer would look something like this:
275
481
 
276
482
  ```ruby
277
483
  Paperclip::Attachment.default_options[:storage] = :fog
278
- Paperclip::Attachment.default_options[:fog_credentials] = {:provider => "Local", :local_root => "#{Rails.root}/public"}
484
+ Paperclip::Attachment.default_options[:fog_credentials] = { provider: "Local", local_root: "#{Rails.root}/public"}
279
485
  Paperclip::Attachment.default_options[:fog_directory] = ""
280
486
  Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"
281
487
  ```
488
+ ---
282
489
 
283
490
  Migrations
284
491
  ----------
285
492
 
286
- Paperclip defines several migration methods which can be used to create necessary columns in your
287
- model. There are two types of method:
493
+ Paperclip defines several migration methods which can be used to create the necessary columns in your
494
+ model. There are two types of helper methods to aid in this, as follows:
495
+
496
+ ### Add Attachment Column To A Table
288
497
 
289
- ### Table Definition
498
+ The `attachment` helper can be used when creating a table:
290
499
 
291
500
  ```ruby
292
- class AddAttachmentToUsers < ActiveRecord::Migration
293
- def self.up
501
+ class CreateUsersWithAttachments < ActiveRecord::Migration
502
+ def up
294
503
  create_table :users do |t|
295
504
  t.attachment :avatar
296
505
  end
297
506
  end
507
+
508
+ # This is assuming you are only using the users table for Paperclip attachment. Drop with care!
509
+ def down
510
+ drop_table :users
511
+ end
298
512
  end
299
513
  ```
300
514
 
301
- If you're using Rails 3.2 or newer, this method works in `change` method as well:
515
+ You can also use the `change` method, instead of the `up`/`down` combination above, as shown below:
302
516
 
303
517
  ```ruby
304
- class AddAttachmentToUsers < ActiveRecord::Migration
518
+ class CreateUsersWithAttachments < ActiveRecord::Migration
305
519
  def change
306
520
  create_table :users do |t|
307
521
  t.attachment :avatar
@@ -312,33 +526,37 @@ end
312
526
 
313
527
  ### Schema Definition
314
528
 
529
+ Alternatively, the `add_attachment` and `remove_attachment` methods can be used to add new Paperclip columns to an existing table:
530
+
315
531
  ```ruby
316
- class AddAttachmentToUsers < ActiveRecord::Migration
317
- def self.up
532
+ class AddAttachmentColumnsToUsers < ActiveRecord::Migration
533
+ def up
318
534
  add_attachment :users, :avatar
319
535
  end
320
536
 
321
- def self.down
537
+ def down
322
538
  remove_attachment :users, :avatar
323
539
  end
324
540
  end
325
541
  ```
326
542
 
327
- If you're using Rails 3.2 or newer, you only need `add_attachment` in your `change` method:
543
+ Or you can do this with the `change` method:
328
544
 
329
545
  ```ruby
330
- class AddAttachmentToUsers < ActiveRecord::Migration
546
+ class AddAttachmentColumnsToUsers < ActiveRecord::Migration
331
547
  def change
332
548
  add_attachment :users, :avatar
333
549
  end
334
550
  end
335
551
  ```
336
552
 
337
- ### Vintage syntax
553
+ ### Vintage Syntax
338
554
 
339
- Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) are still supported in
555
+ Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) is still supported in
340
556
  Paperclip 3.x, but you're advised to update those migration files to use this new syntax.
341
557
 
558
+ ---
559
+
342
560
  Storage
343
561
  -------
344
562
 
@@ -351,6 +569,7 @@ Paperclip ships with 3 storage adapters:
351
569
  If you would like to use Paperclip with another storage, you can install these
352
570
  gems along side with Paperclip:
353
571
 
572
+ * [paperclip-azure](https://github.com/supportify/paperclip-azure)
354
573
  * [paperclip-azure-storage](https://github.com/gmontard/paperclip-azure-storage)
355
574
  * [paperclip-dropbox](https://github.com/janko-m/paperclip-dropbox)
356
575
 
@@ -359,9 +578,9 @@ gems along side with Paperclip:
359
578
  The files that are assigned as attachments are, by default, placed in the
360
579
  directory specified by the `:path` option to `has_attached_file`. By default, this
361
580
  location is `:rails_root/public/system/:class/:attachment/:id_partition/:style/:filename`.
362
- This location was chosen because on standard Capistrano deployments, the
363
- `public/system` directory is symlinked to the app's shared directory, meaning it
364
- will survive between deployments. For example, using that `:path`, you may have a
581
+ This location was chosen because, on standard Capistrano deployments, the
582
+ `public/system` directory can be symlinked to the app's shared directory, meaning it
583
+ survives between deployments. For example, using that `:path`, you may have a
365
584
  file at
366
585
 
367
586
  /data/myapp/releases/20081229172410/public/system/users/avatar/000/000/013/small/my_pic.png
@@ -373,12 +592,12 @@ You may also choose to store your files using Amazon's S3 service. To do so, inc
373
592
  the `aws-sdk` gem in your Gemfile:
374
593
 
375
594
  ```ruby
376
- gem 'aws-sdk', '~> 1.5.7'
595
+ gem 'aws-sdk', '~> 2.3.0'
377
596
  ```
378
597
 
379
598
  And then you can specify using S3 from `has_attached_file`.
380
599
  You can find more information about configuring and using S3 storage in
381
- [the `Paperclip::Storage::S3` documentation](http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
600
+ [the `Paperclip::Storage::S3` documentation](http://www.rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
382
601
 
383
602
  Files on the local filesystem (and in the Rails app's public directory) will be
384
603
  available to the internet at large. If you require access control, it's
@@ -387,63 +606,117 @@ both the `:path` and `:url` options in order to make sure the files are unavaila
387
606
  to the public. Both `:path` and `:url` allow the same set of interpolated
388
607
  variables.
389
608
 
609
+ ---
610
+
611
+ IO Adapters
612
+ -----------
613
+
614
+ When a file is uploaded or attached, it can be in one of a few different input
615
+ forms, from Rails' UploadedFile object to a StringIO to a Tempfile or even a
616
+ simple String that is a URL that points to an image.
617
+
618
+ Paperclip will accept, by default, many of these sources. It also is capable of
619
+ handling even more with a little configuration. The IO Adapters that handle
620
+ images from non-local sources are not enabled by default. They can be enabled by
621
+ adding a line similar to the following into `config/initializers/paperclip.rb`:
622
+
623
+ ```ruby
624
+ Paperclip::DataUriAdapter.register
625
+ ```
626
+
627
+ It's best to only enable a remote-loading adapter if you need it. Otherwise
628
+ there's a chance that someone can gain insight into your internal network
629
+ structure using it as a vector.
630
+
631
+ The following adapters are *not* loaded by default:
632
+
633
+ * `Paperclip::UriAdapter` - which accepts a `URI` instance.
634
+ * `Paperclip::HttpUrlProxyAdapter` - which accepts a `http` string.
635
+ * `Paperclip::DataUriAdapter` - which accepts a Base64-encoded `data:` string.
636
+
637
+ ---
638
+
390
639
  Post Processing
391
640
  ---------------
392
641
 
393
642
  Paperclip supports an extensible selection of post-processors. When you define
394
643
  a set of styles for an attachment, by default it is expected that those
395
- "styles" are actually "thumbnails". However, you can do much more than just
396
- thumbnail images. By defining a subclass of Paperclip::Processor, you can
397
- perform any processing you want on the files that are attached. Any file in
398
- your Rails app's lib/paperclip\_processors directory is automatically loaded by
399
- paperclip, allowing you to easily define custom processors. You can specify a
400
- processor with the :processors option to `has_attached_file`:
644
+ "styles" are actually "thumbnails." These are processed by
645
+ `Paperclip::Thumbnail`. For backward compatibility reasons you can pass either
646
+ a single geometry string, or an array containing a geometry and a format that
647
+ the file will be converted to, like so:
401
648
 
402
649
  ```ruby
403
- has_attached_file :scan, :styles => { :text => { :quality => :better } },
404
- :processors => [:ocr]
650
+ has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }
405
651
  ```
406
652
 
407
- This would load the hypothetical class Paperclip::Ocr, which would have the
408
- hash "{ :quality => :better }" passed to it along with the uploaded file. For
409
- more information about defining processors, see Paperclip::Processor.
653
+ This will convert the "thumb" style to a 32x32 square in PNG format, regardless
654
+ of what was uploaded. If the format is not specified, it is kept the same (e.g.
655
+ JPGs will remain JPGs). `Paperclip::Thumbnail` uses ImageMagick to process
656
+ images; [ImageMagick's geometry documentation](http://www.imagemagick.org/script/command-line-processing.php#geometry)
657
+ has more information on the accepted style formats.
658
+
659
+ ImageMagick supports a number of environment variables for controlling its resource limits. For example, you can enforce memory or execution time limits by setting the following variables in your application's process environment:
660
+
661
+ * `MAGICK_MEMORY_LIMIT=128MiB`
662
+ * `MAGICK_MAP_LIMIT=64MiB`
663
+ * `MAGICK_TIME_LIMIT=30`
664
+
665
+ For a full list of variables and description, see [ImageMagick's resources documentation](http://www.imagemagick.org/script/resources.php).
666
+
667
+ ---
410
668
 
411
- The default processor is Paperclip::Thumbnail. For backwards compatibility
412
- reasons, you can pass a single geometry string or an array containing a
413
- geometry and a format, which the file will be converted to, like so:
669
+ Custom Attachment Processors
670
+ -------
671
+
672
+ You can write your own custom attachment processors to carry out tasks like
673
+ adding watermarks, compressing images, or encrypting files. Custom processors
674
+ must be defined within the `Paperclip` module, inherit from
675
+ `Paperclip::Processor` (see [`lib/paperclip/processor.rb`](https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb)),
676
+ and implement a `make` method that returns a `File`. All files in your Rails
677
+ app's `lib/paperclip` and `lib/paperclip_processors` directories will be
678
+ automatically loaded by Paperclip. Processors are specified using the
679
+ `:processors` option to `has_attached_file`:
414
680
 
415
681
  ```ruby
416
- has_attached_file :avatar, :styles => { :thumb => ["32x32#", :png] }
682
+ has_attached_file :scan, styles: { text: { quality: :better } },
683
+ processors: [:ocr]
417
684
  ```
418
685
 
419
- This will convert the "thumb" style to a 32x32 square in png format, regardless
420
- of what was uploaded. If the format is not specified, it is kept the same (i.e.
421
- jpgs will remain jpgs). For more information on the accepted style formats, see
422
- [here](http://www.imagemagick.org/script/command-line-processing.php#geometry).
686
+ This would load the hypothetical class `Paperclip::Ocr`, and pass it the
687
+ options hash `{ quality: :better }`, along with the uploaded file.
423
688
 
424
689
  Multiple processors can be specified, and they will be invoked in the order
425
- they are defined in the :processors array. Each successive processor will
426
- be given the result of the previous processor's execution. All processors will
427
- receive the same parameters, which are what you define in the :styles hash.
428
- For example, assuming we had this definition:
690
+ they are defined in the `:processors` array. Each successive processor is given
691
+ the result from the previous processor. All processors receive the same
692
+ parameters, which are defined in the `:styles` hash. For example, assuming we
693
+ had this definition:
429
694
 
430
695
  ```ruby
431
- has_attached_file :scan, :styles => { :text => { :quality => :better } },
432
- :processors => [:rotator, :ocr]
696
+ has_attached_file :scan, styles: { text: { quality: :better } },
697
+ processors: [:rotator, :ocr]
433
698
  ```
434
699
 
435
- then both the :rotator processor and the :ocr processor would receive the
436
- options "{ :quality => :better }". This parameter may not mean anything to one
437
- or more or the processors, and they are expected to ignore it.
700
+ Both the `:rotator` processor and the `:ocr` processor would receive the
701
+ options `{ quality: :better }`. If a processor receives an option it doesn't
702
+ recognise, it's expected to ignore it.
438
703
 
439
704
  _NOTE: Because processors operate by turning the original attachment into the
440
705
  styles, no processors will be run if there are no styles defined._
441
706
 
442
707
  If you're interested in caching your thumbnail's width, height and size in the
443
- database, take a look at the [paperclip-meta](https://github.com/y8/paperclip-meta) gem.
708
+ database, take a look at the [paperclip-meta](https://github.com/teeparham/paperclip-meta)
709
+ gem.
444
710
 
445
711
  Also, if you're interested in generating the thumbnail on-the-fly, you might want
446
- to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly) gem.
712
+ to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly)
713
+ gem.
714
+
715
+ Paperclip's thumbnail generator (see [`lib/paperclip/thumbnail.rb`](lib/paperclip/thumbnail.rb))
716
+ is implemented as a processor, and may be a good reference for writing your own
717
+ processors.
718
+
719
+ ---
447
720
 
448
721
  Events
449
722
  ------
@@ -459,8 +732,8 @@ normal ActiveRecord callbacks as possible, so if you return false (specifically
459
732
  will halt. Returning false in an `after_filter` will not halt anything, but you
460
733
  can access the model and the attachment if necessary.
461
734
 
462
- _NOTE: Post processing will not even *start* if the attachment is not valid
463
- according to the validations. Your callbacks and processors will *only* be
735
+ _NOTE: Post processing will not even **start** if the attachment is not valid
736
+ according to the validations. Your callbacks and processors will **only** be
464
737
  called with valid attachments._
465
738
 
466
739
  ```ruby
@@ -475,6 +748,8 @@ class Message < ActiveRecord::Base
475
748
  end
476
749
  ```
477
750
 
751
+ ---
752
+
478
753
  URI Obfuscation
479
754
  ---------------
480
755
 
@@ -485,8 +760,8 @@ Example Usage:
485
760
 
486
761
  ```ruby
487
762
  has_attached_file :avatar, {
488
- :url => "/system/:hash.:extension",
489
- :hash_secret => "longSecretString"
763
+ url: "/system/:hash.:extension",
764
+ hash_secret: "longSecretString"
490
765
  }
491
766
  ```
492
767
 
@@ -494,46 +769,54 @@ has_attached_file :avatar, {
494
769
  The `:hash` interpolation will be replaced with a unique hash made up of whatever
495
770
  is specified in `:hash_data`. The default value for `:hash_data` is `":class/:attachment/:id/:style/:updated_at"`.
496
771
 
497
- `:hash_secret` is required, an exception will be raised if `:hash` is used without `:hash_secret` present.
772
+ `:hash_secret` is required - an exception will be raised if `:hash` is used without `:hash_secret` present.
498
773
 
499
- For more on this feature read the author's own explanation. [https://github.com/thoughtbot/paperclip/pull/416](https://github.com/thoughtbot/paperclip/pull/416)
774
+ For more on this feature, read [the author's own explanation](https://github.com/thoughtbot/paperclip/pull/416)
500
775
 
501
- MD5 Checksum / Fingerprint
776
+ Checksum / Fingerprint
502
777
  -------
503
778
 
504
- A MD5 checksum of the original file assigned will be placed in the model if it
779
+ A checksum of the original file assigned will be placed in the model if it
505
780
  has an attribute named fingerprint. Following the user model migration example
506
- above, the migration would look like the following.
781
+ above, the migration would look like the following:
507
782
 
508
783
  ```ruby
509
784
  class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
510
- def self.up
785
+ def up
511
786
  add_column :users, :avatar_fingerprint, :string
512
787
  end
513
788
 
514
- def self.down
789
+ def down
515
790
  remove_column :users, :avatar_fingerprint
516
791
  end
517
792
  end
518
793
  ```
519
794
 
520
- Custom Attachment Processors
795
+ The algorithm can be specified using a configuration option; it defaults to MD5
796
+ for backwards compatibility with Paperclip 5 and earlier.
797
+
798
+ ```ruby
799
+ has_attached_file :some_attachment, adapter_options: { hash_digest: Digest::SHA256 }
800
+ ```
801
+
802
+ Run `CLASS=User ATTACHMENT=avatar rake paperclip:refresh:fingerprints` after
803
+ changing the digest on existing attachments to update the fingerprints in the
804
+ database.
805
+
806
+ File Preservation for Soft-Delete
521
807
  -------
522
808
 
523
- Custom attachment processors can be implemented and their only requirement is
524
- to inherit from `Paperclip::Processor` (see `lib/paperclip/processor.rb`).
525
- For example, when `:styles` are specified for an image attachment, the
526
- thumbnail processor (see `lib/paperclip/thumbnail.rb`) is loaded without having
527
- to specify it as a `:processor` parameter to `has_attached_file`. When any
528
- other processor is defined it must be called out in the `:processors`
529
- parameter if it is to be applied to the attachment. The thumbnail processor
530
- uses the imagemagick `convert` command to do the work of resizing image
531
- thumbnails. It would be easy to create a custom processor that watermarks
532
- an image using imagemagick's `composite` command. Following the
533
- implementation pattern of the thumbnail processor would be a way to implement a
534
- watermark processor. All kinds of attachment processors can be created;
535
- a few utility examples would be compression and encryption processors.
809
+ An option is available to preserve attachments in order to play nicely with soft-deleted models. (acts_as_paranoid, paranoia, etc.)
810
+
811
+ ```ruby
812
+ has_attached_file :some_attachment, {
813
+ preserve_files: true,
814
+ }
815
+ ```
816
+
817
+ This will prevent ```some_attachment``` from being wiped out when the model gets destroyed, so it will still exist when the object is restored later.
536
818
 
819
+ ---
537
820
 
538
821
  Dynamic Configuration
539
822
  ---------------------
@@ -548,7 +831,7 @@ instances.
548
831
  ### Dynamic Styles:
549
832
 
550
833
  Imagine a user model that had different styles based on the role of the user.
551
- Perhaps some users are bosses (e.g. a User model instance responds to #boss?)
834
+ Perhaps some users are bosses (e.g. a User model instance responds to `#boss?`)
552
835
  and merit a bigger avatar thumbnail than regular users. The configuration to
553
836
  determine what style parameters are to be used based on the user role might
554
837
  look as follows where a boss will receive a `300x300` thumbnail otherwise a
@@ -556,7 +839,7 @@ look as follows where a boss will receive a `300x300` thumbnail otherwise a
556
839
 
557
840
  ```ruby
558
841
  class User < ActiveRecord::Base
559
- has_attached_file :avatar, :styles => lambda { |attachment| { :thumb => (attachment.instance.boss? ? "300x300>" : "100x100>") }
842
+ has_attached_file :avatar, styles: lambda { |attachment| { thumb: (attachment.instance.boss? ? "300x300>" : "100x100>") } }
560
843
  end
561
844
  ```
562
845
 
@@ -573,15 +856,17 @@ processors, where a defined `watermark` processor is invoked after the
573
856
 
574
857
  ```ruby
575
858
  class User < ActiveRecord::Base
576
- has_attached_file :avatar, :processors => lambda { |instance| instance.processors }
577
- attr_accessor :watermark
859
+ has_attached_file :avatar, processors: lambda { |instance| instance.processors }
860
+ attr_accessor :processors
578
861
  end
579
862
  ```
580
863
 
864
+ ---
865
+
581
866
  Logging
582
867
  ----------
583
868
 
584
- By default Paperclip outputs logging according to your logger level. If you want to disable logging (e.g. during testing) add this in to your environment's configuration:
869
+ By default, Paperclip outputs logging according to your logger level. If you want to disable logging (e.g. during testing) add this into your environment's configuration:
585
870
  ```ruby
586
871
  Your::Application.configure do
587
872
  ...
@@ -590,11 +875,23 @@ Your::Application.configure do
590
875
  end
591
876
  ```
592
877
 
593
- More information in the [rdocs](http://rdoc.info/github/thoughtbot/paperclip/Paperclip.options)
878
+ More information in the [rdocs](http://www.rubydoc.info/github/thoughtbot/paperclip/Paperclip.options)
879
+
880
+ ---
594
881
 
595
882
  Deployment
596
883
  ----------
597
884
 
885
+ To make Capistrano symlink the `public/system` directory so that attachments
886
+ survive new deployments, set the `linked_dirs` option in your `config/deploy.rb`
887
+ file:
888
+
889
+ ```ruby
890
+ set :linked_dirs, fetch(:linked_dirs, []).push('public/system')
891
+ ```
892
+
893
+ ### Attachment Styles
894
+
598
895
  Paperclip is aware of new attachment styles you have added in previous deploys. The only thing you should do after each deployment is to call
599
896
  `rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
600
897
  by default. You can change it by:
@@ -606,30 +903,36 @@ Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachment
606
903
  Here is an example for Capistrano:
607
904
 
608
905
  ```ruby
609
- namespace :deploy do
906
+ namespace :paperclip do
610
907
  desc "build missing paperclip styles"
611
- task :build_missing_paperclip_styles, :roles => :app do
612
- run "cd #{release_path}; RAILS_ENV=production bundle exec rake paperclip:refresh:missing_styles"
908
+ task :build_missing_styles do
909
+ on roles(:app) do
910
+ within release_path do
911
+ with rails_env: fetch(:rails_env) do
912
+ execute :rake, "paperclip:refresh:missing_styles"
913
+ end
914
+ end
915
+ end
613
916
  end
614
917
  end
615
918
 
616
- after("deploy:update_code", "deploy:build_missing_paperclip_styles")
919
+ after("deploy:compile_assets", "paperclip:build_missing_styles")
617
920
  ```
618
921
 
619
922
  Now you don't have to remember to refresh thumbnails in production every time you add a new style.
620
- Unfortunately it does not work with dynamic styles - it just ignores them.
923
+ Unfortunately, it does not work with dynamic styles - it just ignores them.
621
924
 
622
925
  If you already have a working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
623
926
  Paperclip about existing styles. Simply create a `paperclip_attachments.yml` file by hand. For example:
624
927
 
625
928
  ```ruby
626
929
  class User < ActiveRecord::Base
627
- has_attached_file :avatar, :styles => {:thumb => 'x100', :croppable => '600x600>', :big => '1000x1000>'}
930
+ has_attached_file :avatar, styles: { thumb: 'x100', croppable: '600x600>', big: '1000x1000>' }
628
931
  end
629
932
 
630
933
  class Book < ActiveRecord::Base
631
- has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
632
- has_attached_file :sample, :styles => {:thumb => 'x100'}
934
+ has_attached_file :cover, styles: { small: 'x100', large: '1000x1000>' }
935
+ has_attached_file :sample, styles: { thumb: 'x100' }
633
936
  end
634
937
  ```
635
938
 
@@ -650,11 +953,13 @@ Then in `RAILS_ROOT/public/system/paperclip_attachments.yml`:
650
953
  - :thumb
651
954
  ```
652
955
 
956
+ ---
957
+
653
958
  Testing
654
959
  -------
655
960
 
656
961
  Paperclip provides rspec-compatible matchers for testing attachments. See the
657
- documentation on [Paperclip::Shoulda::Matchers](http://rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
962
+ documentation on [Paperclip::Shoulda::Matchers](http://www.rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
658
963
  for more information.
659
964
 
660
965
  **Parallel Tests**
@@ -673,9 +978,40 @@ else
673
978
  end
674
979
  ```
675
980
 
676
- The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or the
981
+ The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or a
677
982
  similar mechanism for whichever parallel testing library you use.
678
983
 
984
+ **Integration Tests**
985
+
986
+ Using integration tests with FactoryGirl may save multiple copies of
987
+ your test files within the app. To avoid this, specify a custom path in
988
+ the `config/environments/test.rb` like so:
989
+
990
+ ```ruby
991
+ Paperclip::Attachment.default_options[:path] = "#{Rails.root}/spec/test_files/:class/:id_partition/:style.:extension"
992
+ ```
993
+
994
+ Then, make sure to delete that directory after the test suite runs by adding
995
+ this to `spec_helper.rb`.
996
+
997
+ ```ruby
998
+ config.after(:suite) do
999
+ FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
1000
+ end
1001
+ ```
1002
+
1003
+ **Example of test configuration with Factory Girl**
1004
+
1005
+
1006
+ ```ruby
1007
+ FactoryGirl.define do
1008
+ factory :user do
1009
+ avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") }
1010
+ end
1011
+ end
1012
+ ```
1013
+ ---
1014
+
679
1015
  Contributing
680
1016
  ------------
681
1017
 
@@ -683,27 +1019,33 @@ If you'd like to contribute a feature or bugfix: Thanks! To make sure your
683
1019
  fix/feature has a high chance of being included, please read the following
684
1020
  guidelines:
685
1021
 
686
- 1. Ask on the [mailing list](http://groups.google.com/group/paperclip-plugin), or
687
- post a new [GitHub Issue](http://github.com/thoughtbot/paperclip/issues).
1022
+ 1. Post a [pull request](https://github.com/thoughtbot/paperclip/compare/).
688
1023
  2. Make sure there are tests! We will not accept any patch that is not tested.
689
1024
  It's a rare time when explicit tests aren't needed. If you have questions
690
- about writing tests for paperclip, please ask the mailing list.
1025
+ about writing tests for paperclip, please open a
1026
+ [GitHub issue](https://github.com/thoughtbot/paperclip/issues/new).
691
1027
 
692
- Please see `CONTRIBUTING.md` for more details on contributing and running test.
1028
+ Please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for more details on contributing and running test.
693
1029
 
694
- Credits
1030
+ Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/graphs/contributors)!
1031
+
1032
+ License
695
1033
  -------
696
1034
 
697
- ![thoughtbot](http://thoughtbot.com/logo.png)
1035
+ Paperclip is Copyright © 2008-2017 thoughtbot, inc. It is free software, and may be
1036
+ redistributed under the terms specified in the MIT-LICENSE file.
698
1037
 
699
- Paperclip is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
1038
+ About thoughtbot
1039
+ ----------------
700
1040
 
701
- Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/contributors)!
1041
+ ![thoughtbot](http://presskit.thoughtbot.com/images/thoughtbot-logo-for-readmes.svg)
702
1042
 
1043
+ Paperclip is maintained and funded by thoughtbot.
703
1044
  The names and logos for thoughtbot are trademarks of thoughtbot, inc.
704
1045
 
705
- License
706
- -------
1046
+ We love open source software!
1047
+ See [our other projects][community] or
1048
+ [hire us][hire] to design, develop, and grow your product.
707
1049
 
708
- Paperclip is Copyright © 2008-2013 thoughtbot, inc. It is free software, and may be
709
- redistributed under the terms specified in the MIT-LICENSE file.
1050
+ [community]: https://thoughtbot.com/community?utm_source=github
1051
+ [hire]: https://thoughtbot.com?utm_source=github