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