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