kt-paperclip 6.2.0

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