paperclip 3.4.0 → 6.1.0

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