kt-paperclip 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +3 -0
- data/.gitignore +19 -0
- data/.hound.yml +1050 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +47 -0
- data/Appraisals +24 -0
- data/CONTRIBUTING.md +86 -0
- data/Gemfile +18 -0
- data/LICENSE +24 -0
- data/NEWS +515 -0
- data/README.md +1053 -0
- data/RELEASING.md +17 -0
- data/Rakefile +52 -0
- data/UPGRADING +17 -0
- data/features/basic_integration.feature +85 -0
- data/features/migration.feature +29 -0
- data/features/rake_tasks.feature +62 -0
- data/features/step_definitions/attachment_steps.rb +110 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +257 -0
- data/features/step_definitions/s3_steps.rb +14 -0
- data/features/step_definitions/web_steps.rb +106 -0
- data/features/support/env.rb +12 -0
- data/features/support/fakeweb.rb +11 -0
- data/features/support/file_helpers.rb +34 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +39 -0
- data/features/support/selectors.rb +19 -0
- data/gemfiles/4.2.gemfile +20 -0
- data/gemfiles/5.0.gemfile +20 -0
- data/gemfiles/5.1.gemfile +20 -0
- data/gemfiles/5.2.gemfile +20 -0
- data/gemfiles/6.0.gemfile +20 -0
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +36 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
- data/lib/paperclip.rb +215 -0
- data/lib/paperclip/attachment.rb +617 -0
- data/lib/paperclip/attachment_registry.rb +60 -0
- data/lib/paperclip/callbacks.rb +42 -0
- data/lib/paperclip/content_type_detector.rb +80 -0
- data/lib/paperclip/errors.rb +34 -0
- data/lib/paperclip/file_command_content_type_detector.rb +28 -0
- data/lib/paperclip/filename_cleaner.rb +15 -0
- data/lib/paperclip/geometry.rb +157 -0
- data/lib/paperclip/geometry_detector_factory.rb +45 -0
- data/lib/paperclip/geometry_parser_factory.rb +31 -0
- data/lib/paperclip/glue.rb +17 -0
- data/lib/paperclip/has_attached_file.rb +116 -0
- data/lib/paperclip/helpers.rb +60 -0
- data/lib/paperclip/interpolations.rb +201 -0
- data/lib/paperclip/interpolations/plural_cache.rb +18 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +47 -0
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
- data/lib/paperclip/io_adapters/registry.rb +36 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
- data/lib/paperclip/io_adapters/uri_adapter.rb +68 -0
- data/lib/paperclip/locales/en.yml +18 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers.rb +64 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
- data/lib/paperclip/media_type_spoof_detector.rb +90 -0
- data/lib/paperclip/missing_attachment_styles.rb +84 -0
- data/lib/paperclip/processor.rb +56 -0
- data/lib/paperclip/processor_helpers.rb +52 -0
- data/lib/paperclip/rails_environment.rb +21 -0
- data/lib/paperclip/railtie.rb +31 -0
- data/lib/paperclip/schema.rb +81 -0
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/storage/filesystem.rb +99 -0
- data/lib/paperclip/storage/fog.rb +252 -0
- data/lib/paperclip/storage/s3.rb +461 -0
- data/lib/paperclip/style.rb +106 -0
- data/lib/paperclip/tempfile.rb +42 -0
- data/lib/paperclip/tempfile_factory.rb +22 -0
- data/lib/paperclip/thumbnail.rb +131 -0
- data/lib/paperclip/url_generator.rb +76 -0
- data/lib/paperclip/validators.rb +73 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
- data/lib/paperclip/validators/attachment_file_name_validator.rb +75 -0
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +109 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
- data/lib/paperclip/version.rb +3 -0
- data/lib/tasks/paperclip.rake +140 -0
- data/paperclip.gemspec +50 -0
- data/shoulda_macros/paperclip.rb +134 -0
- data/spec/database.yml +4 -0
- data/spec/paperclip/attachment_definitions_spec.rb +13 -0
- data/spec/paperclip/attachment_processing_spec.rb +79 -0
- data/spec/paperclip/attachment_registry_spec.rb +158 -0
- data/spec/paperclip/attachment_spec.rb +1590 -0
- data/spec/paperclip/content_type_detector_spec.rb +47 -0
- data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
- data/spec/paperclip/filename_cleaner_spec.rb +13 -0
- data/spec/paperclip/geometry_detector_spec.rb +38 -0
- data/spec/paperclip/geometry_parser_spec.rb +73 -0
- data/spec/paperclip/geometry_spec.rb +255 -0
- data/spec/paperclip/glue_spec.rb +42 -0
- data/spec/paperclip/has_attached_file_spec.rb +78 -0
- data/spec/paperclip/integration_spec.rb +702 -0
- data/spec/paperclip/interpolations_spec.rb +270 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +140 -0
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +137 -0
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
- data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +221 -0
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
- data/spec/paperclip/paperclip_spec.rb +196 -0
- data/spec/paperclip/plural_cache_spec.rb +37 -0
- data/spec/paperclip/processor_helpers_spec.rb +57 -0
- data/spec/paperclip/processor_spec.rb +26 -0
- data/spec/paperclip/rails_environment_spec.rb +30 -0
- data/spec/paperclip/rake_spec.rb +103 -0
- data/spec/paperclip/schema_spec.rb +252 -0
- data/spec/paperclip/storage/filesystem_spec.rb +79 -0
- data/spec/paperclip/storage/fog_spec.rb +560 -0
- data/spec/paperclip/storage/s3_live_spec.rb +188 -0
- data/spec/paperclip/storage/s3_spec.rb +1695 -0
- data/spec/paperclip/style_spec.rb +251 -0
- data/spec/paperclip/tempfile_factory_spec.rb +33 -0
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +504 -0
- data/spec/paperclip/url_generator_spec.rb +221 -0
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +159 -0
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +235 -0
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
- data/spec/paperclip/validators_spec.rb +164 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/assertions.rb +84 -0
- data/spec/support/fake_model.rb +24 -0
- data/spec/support/fake_rails.rb +12 -0
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/bad.png +1 -0
- data/spec/support/fixtures/empty.html +1 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +8 -0
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/s3.yml +8 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +1 -0
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +5 -0
- data/spec/support/matchers/exist.rb +5 -0
- data/spec/support/matchers/have_column.rb +23 -0
- data/spec/support/mock_attachment.rb +24 -0
- data/spec/support/mock_interpolator.rb +24 -0
- data/spec/support/mock_url_generator_builder.rb +26 -0
- data/spec/support/model_reconstruction.rb +72 -0
- data/spec/support/reporting.rb +11 -0
- data/spec/support/test_data.rb +13 -0
- data/spec/support/version_helper.rb +9 -0
- metadata +586 -0
data/README.md
ADDED
@@ -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 © 2008-2017 thoughtbot, inc. It is free software, and may be
|
1053
|
+
redistributed under the terms specified in the MIT-LICENSE file.
|