paperclip 3.5.4 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  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 +17 -20
  7. data/Appraisals +4 -16
  8. data/CONTRIBUTING.md +29 -13
  9. data/Gemfile +11 -3
  10. data/LICENSE +1 -3
  11. data/NEWS +241 -49
  12. data/README.md +471 -166
  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 +9 -3
  31. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +2 -2
  32. data/lib/paperclip/attachment.rb +151 -46
  33. data/lib/paperclip/attachment_registry.rb +3 -2
  34. data/lib/paperclip/callbacks.rb +13 -1
  35. data/lib/paperclip/content_type_detector.rb +26 -22
  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 +5 -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 +15 -11
  43. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  44. data/lib/paperclip/interpolations.rb +26 -13
  45. data/lib/paperclip/io_adapters/abstract_adapter.rb +32 -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 +7 -7
  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 +90 -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 +37 -19
  69. data/lib/paperclip/storage/s3.rb +129 -69
  70. data/lib/paperclip/style.rb +8 -2
  71. data/lib/paperclip/tempfile_factory.rb +5 -1
  72. data/lib/paperclip/thumbnail.rb +30 -18
  73. data/lib/paperclip/url_generator.rb +26 -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 +11 -4
  81. data/lib/paperclip/version.rb +3 -1
  82. data/lib/paperclip.rb +30 -11
  83. data/lib/tasks/paperclip.rake +34 -5
  84. data/paperclip.gemspec +21 -16
  85. data/shoulda_macros/paperclip.rb +0 -1
  86. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  87. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +17 -20
  88. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  89. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +502 -407
  90. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +17 -20
  91. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  92. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  93. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  94. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  95. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +50 -52
  96. data/spec/paperclip/glue_spec.rb +44 -0
  97. data/spec/paperclip/has_attached_file_spec.rb +158 -0
  98. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +137 -128
  99. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +70 -46
  100. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +132 -0
  101. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +33 -32
  102. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +89 -0
  103. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  104. data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +38 -42
  105. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +121 -0
  106. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  107. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  108. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +12 -9
  109. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +21 -18
  110. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +46 -46
  111. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +172 -0
  112. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  113. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +109 -0
  114. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  115. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  116. data/spec/paperclip/media_type_spoof_detector_spec.rb +94 -0
  117. data/spec/paperclip/meta_class_spec.rb +30 -0
  118. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  119. data/spec/paperclip/paperclip_spec.rb +192 -0
  120. data/spec/paperclip/plural_cache_spec.rb +37 -0
  121. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  122. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +7 -7
  123. data/spec/paperclip/rails_environment_spec.rb +33 -0
  124. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  125. data/spec/paperclip/schema_spec.rb +248 -0
  126. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  127. data/spec/paperclip/storage/fog_spec.rb +566 -0
  128. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  129. data/spec/paperclip/storage/s3_spec.rb +1693 -0
  130. data/spec/paperclip/style_spec.rb +255 -0
  131. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  132. data/spec/paperclip/tempfile_spec.rb +35 -0
  133. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +153 -134
  134. data/spec/paperclip/url_generator_spec.rb +222 -0
  135. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  136. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  137. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +20 -20
  138. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +77 -64
  139. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  140. data/spec/paperclip/validators_spec.rb +164 -0
  141. data/spec/spec_helper.rb +47 -0
  142. data/spec/support/assertions.rb +82 -0
  143. data/spec/support/conditional_filter_helper.rb +5 -0
  144. data/spec/support/fake_model.rb +25 -0
  145. data/spec/support/fake_rails.rb +12 -0
  146. data/spec/support/fixtures/empty.html +1 -0
  147. data/spec/support/fixtures/empty.xlsx +0 -0
  148. data/spec/support/fixtures/spaced file.jpg +0 -0
  149. data/spec/support/matchers/accept.rb +5 -0
  150. data/spec/support/matchers/exist.rb +5 -0
  151. data/spec/support/matchers/have_column.rb +23 -0
  152. data/{test → spec}/support/mock_attachment.rb +2 -0
  153. data/{test → spec}/support/mock_url_generator_builder.rb +2 -2
  154. data/spec/support/model_reconstruction.rb +68 -0
  155. data/spec/support/reporting.rb +11 -0
  156. data/spec/support/test_data.rb +13 -0
  157. data/spec/support/version_helper.rb +9 -0
  158. metadata +348 -225
  159. data/RUNNING_TESTS.md +0 -4
  160. data/cucumber/paperclip_steps.rb +0 -6
  161. data/gemfiles/3.0.gemfile +0 -11
  162. data/gemfiles/3.1.gemfile +0 -11
  163. data/gemfiles/3.2.gemfile +0 -11
  164. data/gemfiles/4.0.gemfile +0 -11
  165. data/test/attachment_definitions_test.rb +0 -12
  166. data/test/attachment_registry_test.rb +0 -88
  167. data/test/file_command_content_type_detector_test.rb +0 -27
  168. data/test/filename_cleaner_test.rb +0 -14
  169. data/test/generator_test.rb +0 -84
  170. data/test/geometry_detector_test.rb +0 -24
  171. data/test/has_attached_file_test.rb +0 -125
  172. data/test/helper.rb +0 -232
  173. data/test/io_adapters/abstract_adapter_test.rb +0 -58
  174. data/test/io_adapters/data_uri_adapter_test.rb +0 -74
  175. data/test/io_adapters/empty_string_adapter_test.rb +0 -18
  176. data/test/io_adapters/http_url_proxy_adapter_test.rb +0 -102
  177. data/test/io_adapters/identity_adapter_test.rb +0 -8
  178. data/test/io_adapters/uri_adapter_test.rb +0 -102
  179. data/test/matchers/have_attached_file_matcher_test.rb +0 -24
  180. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -110
  181. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -69
  182. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -86
  183. data/test/meta_class_test.rb +0 -32
  184. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  185. data/test/paperclip_test.rb +0 -217
  186. data/test/plural_cache_test.rb +0 -36
  187. data/test/schema_test.rb +0 -200
  188. data/test/storage/fog_test.rb +0 -473
  189. data/test/storage/s3_live_test.rb +0 -179
  190. data/test/storage/s3_test.rb +0 -1356
  191. data/test/style_test.rb +0 -213
  192. data/test/support/mock_model.rb +0 -2
  193. data/test/tempfile_factory_test.rb +0 -17
  194. data/test/url_generator_test.rb +0 -187
  195. data/test/validators/attachment_content_type_validator_test.rb +0 -324
  196. data/test/validators_test.rb +0 -61
  197. /data/{test → spec}/database.yml +0 -0
  198. /data/{test → spec/support}/fixtures/12k.png +0 -0
  199. /data/{test → spec/support}/fixtures/50x50.png +0 -0
  200. /data/{test → spec/support}/fixtures/5k.png +0 -0
  201. /data/{test → spec/support}/fixtures/animated +0 -0
  202. /data/{test → spec/support}/fixtures/animated.gif +0 -0
  203. /data/{test → spec/support}/fixtures/animated.unknown +0 -0
  204. /data/{test → spec/support}/fixtures/bad.png +0 -0
  205. /data/{test → spec/support}/fixtures/fog.yml +0 -0
  206. /data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  207. /data/{test → spec/support}/fixtures/s3.yml +0 -0
  208. /data/{test → spec/support}/fixtures/spaced file.png +0 -0
  209. /data/{test → spec/support}/fixtures/text.txt +0 -0
  210. /data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  211. /data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  212. /data/{test → spec}/support/mock_interpolator.rb +0 -0
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,24 +167,18 @@ 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.2.1"
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:
@@ -93,67 +190,61 @@ class ModuleName < ActiveRecord::Base
93
190
  end
94
191
  ```
95
192
 
193
+ ---
194
+
96
195
  Quick Start
97
196
  -----------
98
197
 
99
198
  ### Models
100
199
 
101
- **Rails 3**
102
-
103
- ```ruby
104
- class User < ActiveRecord::Base
105
- attr_accessible :avatar
106
- has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
107
- end
108
- ```
109
-
110
- **Rails 4**
111
-
112
200
  ```ruby
113
201
  class User < ActiveRecord::Base
114
- 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/
115
204
  end
116
205
  ```
117
206
 
118
207
  ### Migrations
119
208
 
209
+
210
+ Assuming you have a `users` table, add an `avatar` column to the `users` table:
120
211
  ```ruby
121
212
  class AddAvatarColumnsToUsers < ActiveRecord::Migration
122
- def self.up
213
+ def up
123
214
  add_attachment :users, :avatar
124
215
  end
125
216
 
126
- def self.down
217
+ def down
127
218
  remove_attachment :users, :avatar
128
219
  end
129
220
  end
130
221
  ```
131
222
 
132
- (Or you can use migration generator: `rails generate paperclip user avatar`)
223
+ (Or you can use the Rails migration generator: `rails generate paperclip user avatar`)
133
224
 
134
225
  ### Edit and New Views
135
-
226
+ Make sure you have corresponding methods in your controller:
136
227
  ```erb
137
- <%= form_for @user, :url => users_path, :html => { :multipart => true } do |form| %>
228
+ <%= form_for @user, url: users_path, html: { multipart: true } do |form| %>
138
229
  <%= form.file_field :avatar %>
230
+ <%= form.submit %>
139
231
  <% end %>
140
232
  ```
141
233
 
142
- ### Controller
234
+ ### Edit and New Views with [Simple Form](https://github.com/plataformatec/simple_form)
143
235
 
144
- **Rails 3**
145
-
146
- ```ruby
147
- def create
148
- @user = User.create( params[:user] )
149
- end
236
+ ```erb
237
+ <%= simple_form_for @user, url: users_path do |form| %>
238
+ <%= form.input :avatar, as: :file %>
239
+ <%= form.submit %>
240
+ <% end %>
150
241
  ```
151
242
 
152
- **Rails 4**
243
+ ### Controller
153
244
 
154
245
  ```ruby
155
246
  def create
156
- @user = User.create( user_params )
247
+ @user = User.create(user_params)
157
248
  end
158
249
 
159
250
  private
@@ -166,14 +257,24 @@ def user_params
166
257
  end
167
258
  ```
168
259
 
169
- ### Show View
170
-
260
+ ### View Helpers
261
+ Add these to the view where you want your images displayed:
171
262
  ```erb
172
263
  <%= image_tag @user.avatar.url %>
173
264
  <%= image_tag @user.avatar.url(:medium) %>
174
265
  <%= image_tag @user.avatar.url(:thumb) %>
175
266
  ```
176
267
 
268
+ ### Checking a File Exists
269
+
270
+ There are two methods for checking if a file exists:
271
+
272
+ - `file?` and `present?` checks if the `_file_name` field is populated
273
+ - `exists?` checks if the file exists (will perform a TCP connection if stored in the cloud)
274
+
275
+ Keep this in mind if you are checking if files are present in a loop. The first
276
+ version is significantly more performant, but has different semantics.
277
+
177
278
  ### Deleting an Attachment
178
279
 
179
280
  Set the attribute to `nil` and save.
@@ -182,14 +283,15 @@ Set the attribute to `nil` and save.
182
283
  @user.avatar = nil
183
284
  @user.save
184
285
  ```
286
+ ---
185
287
 
186
288
  Usage
187
289
  -----
188
290
 
189
- The basics of paperclip are quite simple: Declare that your model has an
291
+ The basics of Paperclip are quite simple: Declare that your model has an
190
292
  attachment with the `has_attached_file` method, and give it a name.
191
293
 
192
- Paperclip will wrap up up to four attributes (all prefixed with that attachment's name,
294
+ Paperclip will wrap up to four attributes (all prefixed with that attachment's name,
193
295
  so you can have multiple attachments per model if you wish) and give them a
194
296
  friendly front end. These attributes are:
195
297
 
@@ -198,12 +300,12 @@ friendly front end. These attributes are:
198
300
  * `<attachment>_content_type`
199
301
  * `<attachment>_updated_at`
200
302
 
201
- By default, only `<attachment>_file_name` is required for paperclip to operate.
303
+ By default, only `<attachment>_file_name` is required for Paperclip to operate.
202
304
  You'll need to add `<attachment>_content_type` in case you want to use content type
203
305
  validation.
204
306
 
205
- More information about the options to `has_attached_file` is available in the
206
- documentation of [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
307
+ More information about the options passed to `has_attached_file` is available in the
308
+ documentation of [`Paperclip::ClassMethods`](http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
207
309
 
208
310
  Validations
209
311
  -----------
@@ -217,8 +319,10 @@ For validations, Paperclip introduces several validators to validate your attach
217
319
  Example Usage:
218
320
 
219
321
  ```ruby
220
- validates :avatar, :attachment_presence => true
221
- validates_with AttachmentPresenceValidator, :attributes => :avatar
322
+ validates :avatar, attachment_presence: true
323
+ validates_with AttachmentPresenceValidator, attributes: :avatar
324
+ validates_with AttachmentSizeValidator, attributes: :avatar, less_than: 1.megabytes
325
+
222
326
  ```
223
327
 
224
328
  Validators can also be defined using the old helper style:
@@ -236,18 +340,18 @@ validates_attachment_presence :avatar
236
340
  Lastly, you can also define multiple validations on a single attachment using `validates_attachment`:
237
341
 
238
342
  ```ruby
239
- validates_attachment :avatar, :presence => true,
240
- :content_type => { :content_type => "image/jpg" },
241
- :size => { :in => 0..10.kilobytes }
343
+ validates_attachment :avatar, presence: true,
344
+ content_type: { content_type: "image/jpeg" },
345
+ size: { in: 0..10.kilobytes }
242
346
  ```
243
347
 
244
- _NOTE: Post processing will not even *start* if the attachment is not valid
245
- according to the validations. Your callbacks and processors will *only* be
348
+ _NOTE: Post-processing will not even **start** if the attachment is not valid
349
+ according to the validations. Your callbacks and processors will **only** be
246
350
  called with valid attachments._
247
351
 
248
352
  ```ruby
249
353
  class Message < ActiveRecord::Base
250
- has_attached_file :asset, styles: {thumb: "100x100#"}
354
+ has_attached_file :asset, styles: { thumb: "100x100#" }
251
355
 
252
356
  before_post_process :skip_for_audio
253
357
 
@@ -263,7 +367,7 @@ afterwards, then assign manually:
263
367
 
264
368
  ```ruby
265
369
  class Book < ActiveRecord::Base
266
- has_attached_file :document, styles: {thumbnail: "60x60#"}
370
+ has_attached_file :document, styles: { thumbnail: "60x60#" }
267
371
  validates_attachment :document, content_type: { content_type: "application/pdf" }
268
372
  validates_something_else # Other validations that conflict with Paperclip's
269
373
  end
@@ -296,61 +400,126 @@ image-y ones:
296
400
 
297
401
  ```ruby
298
402
  validates_attachment :avatar,
299
- :content_type => { :content_type => ["image/jpg", "image/gif", "image/png"] }
403
+ content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
300
404
  ```
301
405
 
302
406
  `Paperclip::ContentTypeDetector` will attempt to match a file's extension to an
303
407
  inferred content_type, regardless of the actual contents of the file.
304
408
 
409
+ ---
410
+
411
+ Internationalization (I18n)
412
+ ---------------------------
413
+
414
+ For using or adding locale files in different languages, check the project
415
+ https://github.com/thoughtbot/paperclip-i18n.
416
+
417
+ Security Validations
418
+ ====================
419
+
420
+ Thanks to a report from [Egor Homakov](http://homakov.blogspot.com/) we have
421
+ taken steps to prevent people from spoofing Content-Types and getting data
422
+ you weren't expecting onto your server.
423
+
424
+ NOTE: Starting at version 4.0.0, all attachments are *required* to include a
425
+ content_type validation, a file_name validation, or to explicitly state that
426
+ they're not going to have either. *Paperclip will raise an error* if you do not
427
+ do this.
428
+
429
+ ```ruby
430
+ class ActiveRecord::Base
431
+ has_attached_file :avatar
432
+ # Validate content type
433
+ validates_attachment_content_type :avatar, content_type: /\Aimage/
434
+ # Validate filename
435
+ validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
436
+ # Explicitly do not validate
437
+ do_not_validate_attachment_file_type :avatar
438
+ end
439
+ ```
440
+
441
+ This keeps Paperclip secure-by-default, and will prevent people trying to mess
442
+ with your filesystem.
443
+
444
+ NOTE: Also starting at version 4.0.0, Paperclip has another validation that
445
+ cannot be turned off. This validation will prevent content type spoofing. That
446
+ is, uploading a PHP document (for example) as part of the EXIF tags of a
447
+ well-formed JPEG. This check is limited to the media type (the first part of the
448
+ MIME type, so, 'text' in `text/plain`). This will prevent HTML documents from
449
+ being uploaded as JPEGs, but will not prevent GIFs from being uploaded with a
450
+ `.jpg` extension. This validation will only add validation errors to the form. It
451
+ will not cause errors to be raised.
452
+
453
+ This can sometimes cause false validation errors in applications that use custom
454
+ file extensions. In these cases you may wish to add your custom extension to the
455
+ list of content type mappings by creating `config/initializers/paperclip.rb`:
456
+
457
+ ```ruby
458
+ # Allow ".foo" as an extension for files with the MIME type "text/plain".
459
+ Paperclip.options[:content_type_mappings] = {
460
+ foo: %w(text/plain)
461
+ }
462
+ ```
463
+
464
+ ---
465
+
305
466
  Defaults
306
467
  --------
307
- 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.
468
+ 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.
308
469
 
309
- 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:
470
+ 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:
310
471
 
311
472
  ```ruby
312
473
  module YourApp
313
474
  class Application < Rails::Application
314
475
  # Other code...
315
476
 
316
- config.paperclip_defaults = {:storage => :fog, :fog_credentials => {:provider => "Local", :local_root => "#{Rails.root}/public"}, :fog_directory => "", :fog_host => "localhost"}
477
+ config.paperclip_defaults = { storage: :fog, fog_credentials: { provider: "Local", local_root: "#{Rails.root}/public"}, fog_directory: "", fog_host: "localhost"}
317
478
  end
318
479
  end
319
480
  ```
320
481
 
321
- 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.
482
+ 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.
322
483
 
323
484
  An example Rails initializer would look something like this:
324
485
 
325
486
  ```ruby
326
487
  Paperclip::Attachment.default_options[:storage] = :fog
327
- Paperclip::Attachment.default_options[:fog_credentials] = {:provider => "Local", :local_root => "#{Rails.root}/public"}
488
+ Paperclip::Attachment.default_options[:fog_credentials] = { provider: "Local", local_root: "#{Rails.root}/public"}
328
489
  Paperclip::Attachment.default_options[:fog_directory] = ""
329
490
  Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"
330
491
  ```
492
+ ---
331
493
 
332
494
  Migrations
333
495
  ----------
334
496
 
335
- Paperclip defines several migration methods which can be used to create necessary columns in your
336
- model. There are two types of method:
497
+ Paperclip defines several migration methods which can be used to create the necessary columns in your
498
+ model. There are two types of helper methods to aid in this, as follows:
337
499
 
338
- ### Table Definition
500
+ ### Add Attachment Column To A Table
501
+
502
+ The `attachment` helper can be used when creating a table:
339
503
 
340
504
  ```ruby
341
- class AddAttachmentToUsers < ActiveRecord::Migration
342
- def self.up
505
+ class CreateUsersWithAttachments < ActiveRecord::Migration
506
+ def up
343
507
  create_table :users do |t|
344
508
  t.attachment :avatar
345
509
  end
346
510
  end
511
+
512
+ # This is assuming you are only using the users table for Paperclip attachment. Drop with care!
513
+ def down
514
+ drop_table :users
515
+ end
347
516
  end
348
517
  ```
349
518
 
350
- If you're using Rails 3.2 or newer, this method works in `change` method as well:
519
+ You can also use the `change` method, instead of the `up`/`down` combination above, as shown below:
351
520
 
352
521
  ```ruby
353
- class AddAttachmentToUsers < ActiveRecord::Migration
522
+ class CreateUsersWithAttachments < ActiveRecord::Migration
354
523
  def change
355
524
  create_table :users do |t|
356
525
  t.attachment :avatar
@@ -361,33 +530,37 @@ end
361
530
 
362
531
  ### Schema Definition
363
532
 
533
+ Alternatively, the `add_attachment` and `remove_attachment` methods can be used to add new Paperclip columns to an existing table:
534
+
364
535
  ```ruby
365
- class AddAttachmentToUsers < ActiveRecord::Migration
366
- def self.up
536
+ class AddAttachmentColumnsToUsers < ActiveRecord::Migration
537
+ def up
367
538
  add_attachment :users, :avatar
368
539
  end
369
540
 
370
- def self.down
541
+ def down
371
542
  remove_attachment :users, :avatar
372
543
  end
373
544
  end
374
545
  ```
375
546
 
376
- If you're using Rails 3.2 or newer, you only need `add_attachment` in your `change` method:
547
+ Or you can do this with the `change` method:
377
548
 
378
549
  ```ruby
379
- class AddAttachmentToUsers < ActiveRecord::Migration
550
+ class AddAttachmentColumnsToUsers < ActiveRecord::Migration
380
551
  def change
381
552
  add_attachment :users, :avatar
382
553
  end
383
554
  end
384
555
  ```
385
556
 
386
- ### Vintage syntax
557
+ ### Vintage Syntax
387
558
 
388
- Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) are still supported in
559
+ Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) is still supported in
389
560
  Paperclip 3.x, but you're advised to update those migration files to use this new syntax.
390
561
 
562
+ ---
563
+
391
564
  Storage
392
565
  -------
393
566
 
@@ -400,6 +573,7 @@ Paperclip ships with 3 storage adapters:
400
573
  If you would like to use Paperclip with another storage, you can install these
401
574
  gems along side with Paperclip:
402
575
 
576
+ * [paperclip-azure](https://github.com/supportify/paperclip-azure)
403
577
  * [paperclip-azure-storage](https://github.com/gmontard/paperclip-azure-storage)
404
578
  * [paperclip-dropbox](https://github.com/janko-m/paperclip-dropbox)
405
579
 
@@ -408,9 +582,9 @@ gems along side with Paperclip:
408
582
  The files that are assigned as attachments are, by default, placed in the
409
583
  directory specified by the `:path` option to `has_attached_file`. By default, this
410
584
  location is `:rails_root/public/system/:class/:attachment/:id_partition/:style/:filename`.
411
- This location was chosen because on standard Capistrano deployments, the
412
- `public/system` directory is symlinked to the app's shared directory, meaning it
413
- will survive between deployments. For example, using that `:path`, you may have a
585
+ This location was chosen because, on standard Capistrano deployments, the
586
+ `public/system` directory can be symlinked to the app's shared directory, meaning it
587
+ survives between deployments. For example, using that `:path`, you may have a
414
588
  file at
415
589
 
416
590
  /data/myapp/releases/20081229172410/public/system/users/avatar/000/000/013/small/my_pic.png
@@ -422,12 +596,12 @@ You may also choose to store your files using Amazon's S3 service. To do so, inc
422
596
  the `aws-sdk` gem in your Gemfile:
423
597
 
424
598
  ```ruby
425
- gem 'aws-sdk', '~> 1.5.7'
599
+ gem 'aws-sdk', '~> 2.3.0'
426
600
  ```
427
601
 
428
602
  And then you can specify using S3 from `has_attached_file`.
429
603
  You can find more information about configuring and using S3 storage in
430
- [the `Paperclip::Storage::S3` documentation](http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
604
+ [the `Paperclip::Storage::S3` documentation](http://www.rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
431
605
 
432
606
  Files on the local filesystem (and in the Rails app's public directory) will be
433
607
  available to the internet at large. If you require access control, it's
@@ -436,63 +610,125 @@ both the `:path` and `:url` options in order to make sure the files are unavaila
436
610
  to the public. Both `:path` and `:url` allow the same set of interpolated
437
611
  variables.
438
612
 
613
+ ---
614
+
615
+ IO Adapters
616
+ -----------
617
+
618
+ When a file is uploaded or attached, it can be in one of a few different input
619
+ forms, from Rails' UploadedFile object to a StringIO to a Tempfile or even a
620
+ simple String that is a URL that points to an image.
621
+
622
+ Paperclip will accept, by default, many of these sources. It also is capable of
623
+ handling even more with a little configuration. The IO Adapters that handle
624
+ images from non-local sources are not enabled by default. They can be enabled by
625
+ adding a line similar to the following into `config/initializers/paperclip.rb`:
626
+
627
+ ```ruby
628
+ Paperclip::DataUriAdapter.register
629
+ ```
630
+
631
+ It's best to only enable a remote-loading adapter if you need it. Otherwise
632
+ there's a chance that someone can gain insight into your internal network
633
+ structure using it as a vector.
634
+
635
+ The following adapters are *not* loaded by default:
636
+
637
+ * `Paperclip::UriAdapter` - which accepts a `URI` instance.
638
+ * `Paperclip::HttpUrlProxyAdapter` - which accepts a `http` string.
639
+ * `Paperclip::DataUriAdapter` - which accepts a Base64-encoded `data:` string.
640
+
641
+ ---
642
+
439
643
  Post Processing
440
644
  ---------------
441
645
 
442
646
  Paperclip supports an extensible selection of post-processors. When you define
443
647
  a set of styles for an attachment, by default it is expected that those
444
- "styles" are actually "thumbnails". However, you can do much more than just
445
- thumbnail images. By defining a subclass of Paperclip::Processor, you can
446
- perform any processing you want on the files that are attached. Any file in
447
- your Rails app's lib/paperclip\_processors directory is automatically loaded by
448
- paperclip, allowing you to easily define custom processors. You can specify a
449
- processor with the :processors option to `has_attached_file`:
648
+ "styles" are actually "thumbnails." These are processed by
649
+ `Paperclip::Thumbnail`. For backward compatibility reasons you can pass either
650
+ a single geometry string, or an array containing a geometry and a format that
651
+ the file will be converted to, like so:
652
+
653
+ ```ruby
654
+ has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }
655
+ ```
656
+
657
+ This will convert the "thumb" style to a 32x32 square in PNG format, regardless
658
+ of what was uploaded. If the format is not specified, it is kept the same (e.g.
659
+ JPGs will remain JPGs). `Paperclip::Thumbnail` uses ImageMagick to process
660
+ images; [ImageMagick's geometry documentation](http://www.imagemagick.org/script/command-line-processing.php#geometry)
661
+ has more information on the accepted style formats.
662
+
663
+ For more fine-grained control of the conversion process, `source_file_options` and `convert_options` can be used to pass flags and settings directly to ImageMagick's powerful Convert tool, [documented here](https://www.imagemagick.org/script/convert.php). For example:
450
664
 
451
665
  ```ruby
452
- has_attached_file :scan, :styles => { :text => { :quality => :better } },
453
- :processors => [:ocr]
666
+ has_attached_file :image, styles: { regular: ['800x800>', :png]},
667
+ source_file_options: { regular: "-density 96 -depth 8 -quality 85" },
668
+ convert_options: { regular: "-posterize 3"}
454
669
  ```
455
670
 
456
- This would load the hypothetical class Paperclip::Ocr, which would have the
457
- hash "{ :quality => :better }" passed to it along with the uploaded file. For
458
- more information about defining processors, see Paperclip::Processor.
671
+ 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:
672
+
673
+ * `MAGICK_MEMORY_LIMIT=128MiB`
674
+ * `MAGICK_MAP_LIMIT=64MiB`
675
+ * `MAGICK_TIME_LIMIT=30`
459
676
 
460
- The default processor is Paperclip::Thumbnail. For backwards compatibility
461
- reasons, you can pass a single geometry string or an array containing a
462
- geometry and a format, which the file will be converted to, like so:
677
+ For a full list of variables and description, see [ImageMagick's resources documentation](http://www.imagemagick.org/script/resources.php).
678
+
679
+ ---
680
+
681
+ Custom Attachment Processors
682
+ -------
683
+
684
+ You can write your own custom attachment processors to carry out tasks like
685
+ adding watermarks, compressing images, or encrypting files. Custom processors
686
+ must be defined within the `Paperclip` module, inherit from
687
+ `Paperclip::Processor` (see [`lib/paperclip/processor.rb`](https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb)),
688
+ and implement a `make` method that returns a `File`. All files in your Rails
689
+ app's `lib/paperclip` and `lib/paperclip_processors` directories will be
690
+ automatically loaded by Paperclip. Processors are specified using the
691
+ `:processors` option to `has_attached_file`:
463
692
 
464
693
  ```ruby
465
- has_attached_file :avatar, :styles => { :thumb => ["32x32#", :png] }
694
+ has_attached_file :scan, styles: { text: { quality: :better } },
695
+ processors: [:ocr]
466
696
  ```
467
697
 
468
- This will convert the "thumb" style to a 32x32 square in png format, regardless
469
- of what was uploaded. If the format is not specified, it is kept the same (i.e.
470
- jpgs will remain jpgs). For more information on the accepted style formats, see
471
- [here](http://www.imagemagick.org/script/command-line-processing.php#geometry).
698
+ This would load the hypothetical class `Paperclip::Ocr`, and pass it the
699
+ options hash `{ quality: :better }`, along with the uploaded file.
472
700
 
473
701
  Multiple processors can be specified, and they will be invoked in the order
474
- they are defined in the :processors array. Each successive processor will
475
- be given the result of the previous processor's execution. All processors will
476
- receive the same parameters, which are what you define in the :styles hash.
477
- For example, assuming we had this definition:
702
+ they are defined in the `:processors` array. Each successive processor is given
703
+ the result from the previous processor. All processors receive the same
704
+ parameters, which are defined in the `:styles` hash. For example, assuming we
705
+ had this definition:
478
706
 
479
707
  ```ruby
480
- has_attached_file :scan, :styles => { :text => { :quality => :better } },
481
- :processors => [:rotator, :ocr]
708
+ has_attached_file :scan, styles: { text: { quality: :better } },
709
+ processors: [:rotator, :ocr]
482
710
  ```
483
711
 
484
- then both the :rotator processor and the :ocr processor would receive the
485
- options "{ :quality => :better }". This parameter may not mean anything to one
486
- or more or the processors, and they are expected to ignore it.
712
+ Both the `:rotator` processor and the `:ocr` processor would receive the
713
+ options `{ quality: :better }`. If a processor receives an option it doesn't
714
+ recognise, it's expected to ignore it.
487
715
 
488
716
  _NOTE: Because processors operate by turning the original attachment into the
489
717
  styles, no processors will be run if there are no styles defined._
490
718
 
491
719
  If you're interested in caching your thumbnail's width, height and size in the
492
- database, take a look at the [paperclip-meta](https://github.com/y8/paperclip-meta) gem.
720
+ database, take a look at the [paperclip-meta](https://github.com/teeparham/paperclip-meta)
721
+ gem.
493
722
 
494
723
  Also, if you're interested in generating the thumbnail on-the-fly, you might want
495
- to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly) gem.
724
+ to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly)
725
+ gem.
726
+
727
+ Paperclip's thumbnail generator (see [`lib/paperclip/thumbnail.rb`](lib/paperclip/thumbnail.rb))
728
+ is implemented as a processor, and may be a good reference for writing your own
729
+ processors.
730
+
731
+ ---
496
732
 
497
733
  Events
498
734
  ------
@@ -508,13 +744,13 @@ normal ActiveRecord callbacks as possible, so if you return false (specifically
508
744
  will halt. Returning false in an `after_filter` will not halt anything, but you
509
745
  can access the model and the attachment if necessary.
510
746
 
511
- _NOTE: Post processing will not even *start* if the attachment is not valid
512
- according to the validations. Your callbacks and processors will *only* be
747
+ _NOTE: Post processing will not even **start** if the attachment is not valid
748
+ according to the validations. Your callbacks and processors will **only** be
513
749
  called with valid attachments._
514
750
 
515
751
  ```ruby
516
752
  class Message < ActiveRecord::Base
517
- has_attached_file :asset, styles: {thumb: "100x100#"}
753
+ has_attached_file :asset, styles: { thumb: "100x100#" }
518
754
 
519
755
  before_post_process :skip_for_audio
520
756
 
@@ -524,6 +760,8 @@ class Message < ActiveRecord::Base
524
760
  end
525
761
  ```
526
762
 
763
+ ---
764
+
527
765
  URI Obfuscation
528
766
  ---------------
529
767
 
@@ -534,8 +772,8 @@ Example Usage:
534
772
 
535
773
  ```ruby
536
774
  has_attached_file :avatar, {
537
- :url => "/system/:hash.:extension",
538
- :hash_secret => "longSecretString"
775
+ url: "/system/:hash.:extension",
776
+ hash_secret: "longSecretString"
539
777
  }
540
778
  ```
541
779
 
@@ -543,46 +781,54 @@ has_attached_file :avatar, {
543
781
  The `:hash` interpolation will be replaced with a unique hash made up of whatever
544
782
  is specified in `:hash_data`. The default value for `:hash_data` is `":class/:attachment/:id/:style/:updated_at"`.
545
783
 
546
- `:hash_secret` is required, an exception will be raised if `:hash` is used without `:hash_secret` present.
784
+ `:hash_secret` is required - an exception will be raised if `:hash` is used without `:hash_secret` present.
547
785
 
548
- 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)
786
+ For more on this feature, read [the author's own explanation](https://github.com/thoughtbot/paperclip/pull/416)
549
787
 
550
- MD5 Checksum / Fingerprint
788
+ Checksum / Fingerprint
551
789
  -------
552
790
 
553
- A MD5 checksum of the original file assigned will be placed in the model if it
791
+ A checksum of the original file assigned will be placed in the model if it
554
792
  has an attribute named fingerprint. Following the user model migration example
555
- above, the migration would look like the following.
793
+ above, the migration would look like the following:
556
794
 
557
795
  ```ruby
558
796
  class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
559
- def self.up
797
+ def up
560
798
  add_column :users, :avatar_fingerprint, :string
561
799
  end
562
800
 
563
- def self.down
801
+ def down
564
802
  remove_column :users, :avatar_fingerprint
565
803
  end
566
804
  end
567
805
  ```
568
806
 
569
- Custom Attachment Processors
807
+ The algorithm can be specified using a configuration option; it defaults to MD5
808
+ for backwards compatibility with Paperclip 5 and earlier.
809
+
810
+ ```ruby
811
+ has_attached_file :some_attachment, adapter_options: { hash_digest: Digest::SHA256 }
812
+ ```
813
+
814
+ Run `CLASS=User ATTACHMENT=avatar rake paperclip:refresh:fingerprints` after
815
+ changing the digest on existing attachments to update the fingerprints in the
816
+ database.
817
+
818
+ File Preservation for Soft-Delete
570
819
  -------
571
820
 
572
- Custom attachment processors can be implemented and their only requirement is
573
- to inherit from `Paperclip::Processor` (see `lib/paperclip/processor.rb`).
574
- For example, when `:styles` are specified for an image attachment, the
575
- thumbnail processor (see `lib/paperclip/thumbnail.rb`) is loaded without having
576
- to specify it as a `:processor` parameter to `has_attached_file`. When any
577
- other processor is defined it must be called out in the `:processors`
578
- parameter if it is to be applied to the attachment. The thumbnail processor
579
- uses the imagemagick `convert` command to do the work of resizing image
580
- thumbnails. It would be easy to create a custom processor that watermarks
581
- an image using imagemagick's `composite` command. Following the
582
- implementation pattern of the thumbnail processor would be a way to implement a
583
- watermark processor. All kinds of attachment processors can be created;
584
- a few utility examples would be compression and encryption processors.
821
+ An option is available to preserve attachments in order to play nicely with soft-deleted models. (acts_as_paranoid, paranoia, etc.)
585
822
 
823
+ ```ruby
824
+ has_attached_file :some_attachment, {
825
+ preserve_files: true,
826
+ }
827
+ ```
828
+
829
+ 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.
830
+
831
+ ---
586
832
 
587
833
  Dynamic Configuration
588
834
  ---------------------
@@ -597,7 +843,7 @@ instances.
597
843
  ### Dynamic Styles:
598
844
 
599
845
  Imagine a user model that had different styles based on the role of the user.
600
- Perhaps some users are bosses (e.g. a User model instance responds to #boss?)
846
+ Perhaps some users are bosses (e.g. a User model instance responds to `#boss?`)
601
847
  and merit a bigger avatar thumbnail than regular users. The configuration to
602
848
  determine what style parameters are to be used based on the user role might
603
849
  look as follows where a boss will receive a `300x300` thumbnail otherwise a
@@ -605,7 +851,7 @@ look as follows where a boss will receive a `300x300` thumbnail otherwise a
605
851
 
606
852
  ```ruby
607
853
  class User < ActiveRecord::Base
608
- has_attached_file :avatar, :styles => lambda { |attachment| { :thumb => (attachment.instance.boss? ? "300x300>" : "100x100>") } }
854
+ has_attached_file :avatar, styles: lambda { |attachment| { thumb: (attachment.instance.boss? ? "300x300>" : "100x100>") } }
609
855
  end
610
856
  ```
611
857
 
@@ -622,15 +868,17 @@ processors, where a defined `watermark` processor is invoked after the
622
868
 
623
869
  ```ruby
624
870
  class User < ActiveRecord::Base
625
- has_attached_file :avatar, :processors => lambda { |instance| instance.processors }
626
- attr_accessor :watermark
871
+ has_attached_file :avatar, processors: lambda { |instance| instance.processors }
872
+ attr_accessor :processors
627
873
  end
628
874
  ```
629
875
 
876
+ ---
877
+
630
878
  Logging
631
879
  ----------
632
880
 
633
- 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:
881
+ 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:
634
882
  ```ruby
635
883
  Your::Application.configure do
636
884
  ...
@@ -639,11 +887,23 @@ Your::Application.configure do
639
887
  end
640
888
  ```
641
889
 
642
- More information in the [rdocs](http://rdoc.info/github/thoughtbot/paperclip/Paperclip.options)
890
+ More information in the [rdocs](http://www.rubydoc.info/github/thoughtbot/paperclip/Paperclip.options)
891
+
892
+ ---
643
893
 
644
894
  Deployment
645
895
  ----------
646
896
 
897
+ To make Capistrano symlink the `public/system` directory so that attachments
898
+ survive new deployments, set the `linked_dirs` option in your `config/deploy.rb`
899
+ file:
900
+
901
+ ```ruby
902
+ set :linked_dirs, fetch(:linked_dirs, []).push('public/system')
903
+ ```
904
+
905
+ ### Attachment Styles
906
+
647
907
  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
648
908
  `rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
649
909
  by default. You can change it by:
@@ -655,30 +915,36 @@ Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachment
655
915
  Here is an example for Capistrano:
656
916
 
657
917
  ```ruby
658
- namespace :deploy do
918
+ namespace :paperclip do
659
919
  desc "build missing paperclip styles"
660
- task :build_missing_paperclip_styles, :roles => :app do
661
- run "cd #{release_path}; RAILS_ENV=production bundle exec rake paperclip:refresh:missing_styles"
920
+ task :build_missing_styles do
921
+ on roles(:app) do
922
+ within release_path do
923
+ with rails_env: fetch(:rails_env) do
924
+ execute :rake, "paperclip:refresh:missing_styles"
925
+ end
926
+ end
927
+ end
662
928
  end
663
929
  end
664
930
 
665
- after("deploy:update_code", "deploy:build_missing_paperclip_styles")
931
+ after("deploy:compile_assets", "paperclip:build_missing_styles")
666
932
  ```
667
933
 
668
934
  Now you don't have to remember to refresh thumbnails in production every time you add a new style.
669
- Unfortunately it does not work with dynamic styles - it just ignores them.
935
+ Unfortunately, it does not work with dynamic styles - it just ignores them.
670
936
 
671
937
  If you already have a working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
672
938
  Paperclip about existing styles. Simply create a `paperclip_attachments.yml` file by hand. For example:
673
939
 
674
940
  ```ruby
675
941
  class User < ActiveRecord::Base
676
- has_attached_file :avatar, :styles => {:thumb => 'x100', :croppable => '600x600>', :big => '1000x1000>'}
942
+ has_attached_file :avatar, styles: { thumb: 'x100', croppable: '600x600>', big: '1000x1000>' }
677
943
  end
678
944
 
679
945
  class Book < ActiveRecord::Base
680
- has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
681
- has_attached_file :sample, :styles => {:thumb => 'x100'}
946
+ has_attached_file :cover, styles: { small: 'x100', large: '1000x1000>' }
947
+ has_attached_file :sample, styles: { thumb: 'x100' }
682
948
  end
683
949
  ```
684
950
 
@@ -699,11 +965,13 @@ Then in `RAILS_ROOT/public/system/paperclip_attachments.yml`:
699
965
  - :thumb
700
966
  ```
701
967
 
968
+ ---
969
+
702
970
  Testing
703
971
  -------
704
972
 
705
973
  Paperclip provides rspec-compatible matchers for testing attachments. See the
706
- documentation on [Paperclip::Shoulda::Matchers](http://rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
974
+ documentation on [Paperclip::Shoulda::Matchers](http://www.rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
707
975
  for more information.
708
976
 
709
977
  **Parallel Tests**
@@ -722,9 +990,40 @@ else
722
990
  end
723
991
  ```
724
992
 
725
- The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or the
993
+ The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or a
726
994
  similar mechanism for whichever parallel testing library you use.
727
995
 
996
+ **Integration Tests**
997
+
998
+ Using integration tests with FactoryBot may save multiple copies of
999
+ your test files within the app. To avoid this, specify a custom path in
1000
+ the `config/environments/test.rb` like so:
1001
+
1002
+ ```ruby
1003
+ Paperclip::Attachment.default_options[:path] = "#{Rails.root}/spec/test_files/:class/:id_partition/:style.:extension"
1004
+ ```
1005
+
1006
+ Then, make sure to delete that directory after the test suite runs by adding
1007
+ this to `spec_helper.rb`.
1008
+
1009
+ ```ruby
1010
+ config.after(:suite) do
1011
+ FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
1012
+ end
1013
+ ```
1014
+
1015
+ **Example of test configuration with Factory Bot**
1016
+
1017
+
1018
+ ```ruby
1019
+ FactoryBot.define do
1020
+ factory :user do
1021
+ avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") }
1022
+ end
1023
+ end
1024
+ ```
1025
+ ---
1026
+
728
1027
  Contributing
729
1028
  ------------
730
1029
 
@@ -738,21 +1037,27 @@ guidelines:
738
1037
  about writing tests for paperclip, please open a
739
1038
  [GitHub issue](https://github.com/thoughtbot/paperclip/issues/new).
740
1039
 
741
- Please see `CONTRIBUTING.md` for more details on contributing and running test.
1040
+ Please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for more details on contributing and running test.
742
1041
 
743
- Credits
1042
+ Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/graphs/contributors)!
1043
+
1044
+ License
744
1045
  -------
745
1046
 
746
- ![thoughtbot](http://thoughtbot.com/logo.png)
1047
+ Paperclip is Copyright © 2008-2017 thoughtbot, inc. It is free software, and may be
1048
+ redistributed under the terms specified in the MIT-LICENSE file.
747
1049
 
748
- Paperclip is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
1050
+ About thoughtbot
1051
+ ----------------
749
1052
 
750
- Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/contributors)!
1053
+ ![thoughtbot](http://presskit.thoughtbot.com/images/thoughtbot-logo-for-readmes.svg)
751
1054
 
1055
+ Paperclip is maintained and funded by thoughtbot.
752
1056
  The names and logos for thoughtbot are trademarks of thoughtbot, inc.
753
1057
 
754
- License
755
- -------
1058
+ We love open source software!
1059
+ See [our other projects][community] or
1060
+ [hire us][hire] to design, develop, and grow your product.
756
1061
 
757
- Paperclip is Copyright © 2008-2013 thoughtbot, inc. It is free software, and may be
758
- redistributed under the terms specified in the MIT-LICENSE file.
1062
+ [community]: https://thoughtbot.com/community?utm_source=github
1063
+ [hire]: https://thoughtbot.com?utm_source=github