paperclip 3.5.2 → 5.2.1
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/.gitignore +0 -6
- data/.hound.yml +1055 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +19 -13
- data/Appraisals +4 -16
- data/CONTRIBUTING.md +29 -13
- data/Gemfile +10 -7
- data/LICENSE +1 -3
- data/NEWS +226 -23
- data/README.md +494 -152
- 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 +0 -2
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
- data/lib/paperclip/attachment.rb +160 -47
- data/lib/paperclip/attachment_registry.rb +4 -1
- data/lib/paperclip/callbacks.rb +13 -1
- data/lib/paperclip/content_type_detector.rb +26 -24
- 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 +10 -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 +14 -10
- data/lib/paperclip/interpolations/plural_cache.rb +6 -5
- data/lib/paperclip/interpolations.rb +27 -14
- data/lib/paperclip/io_adapters/abstract_adapter.rb +28 -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 +8 -8
- 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 +89 -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 +47 -22
- data/lib/paperclip/storage/s3.rb +144 -73
- data/lib/paperclip/style.rb +8 -2
- data/lib/paperclip/tempfile_factory.rb +6 -4
- data/lib/paperclip/thumbnail.rb +26 -14
- data/lib/paperclip/url_generator.rb +25 -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 +12 -3
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +31 -11
- data/lib/tasks/paperclip.rake +34 -5
- data/paperclip.gemspec +18 -17
- data/shoulda_macros/paperclip.rb +13 -3
- data/{test → spec}/database.yml +0 -0
- 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} +524 -400
- data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +17 -19
- data/{test/file_command_content_type_detector_test.rb → spec/paperclip/file_command_content_type_detector_spec.rb} +7 -6
- 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} +141 -133
- data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +70 -46
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +101 -0
- data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +38 -34
- 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 +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 +79 -0
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
- data/{test/paperclip_test.rb → spec/paperclip/paperclip_spec.rb} +46 -71
- 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} +5 -5
- 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 +561 -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} +150 -131
- 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/{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/spec/support/fixtures/empty.html +1 -0
- data/spec/support/fixtures/empty.xlsx +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/spec/support/fixtures/spaced file.jpg +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/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_interpolator.rb +0 -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 +262 -297
- 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 -77
- data/test/filename_cleaner_test.rb +0 -14
- data/test/generator_test.rb +0 -80
- data/test/geometry_detector_test.rb +0 -24
- data/test/has_attached_file_test.rb +0 -125
- data/test/helper.rb +0 -215
- data/test/io_adapters/abstract_adapter_test.rb +0 -58
- data/test/io_adapters/data_uri_adapter_test.rb +0 -67
- data/test/io_adapters/empty_string_adapter_test.rb +0 -17
- data/test/io_adapters/file_adapter_test.rb +0 -119
- 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/plural_cache_test.rb +0 -36
- 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 -1348
- 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 -323
- data/test/validators_test.rb +0 -32
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,80 +167,93 @@ 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.0.0"
|
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:
|
88
185
|
|
89
186
|
```ruby
|
90
187
|
class ModuleName < ActiveRecord::Base
|
91
|
-
|
92
|
-
|
188
|
+
include Paperclip::Glue
|
189
|
+
...
|
93
190
|
end
|
94
191
|
```
|
95
192
|
|
193
|
+
---
|
194
|
+
|
96
195
|
Quick Start
|
97
196
|
-----------
|
98
197
|
|
99
|
-
|
198
|
+
### Models
|
100
199
|
|
101
200
|
```ruby
|
102
201
|
class User < ActiveRecord::Base
|
103
|
-
|
104
|
-
|
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/
|
105
204
|
end
|
106
205
|
```
|
107
206
|
|
108
|
-
|
207
|
+
### Migrations
|
109
208
|
|
110
209
|
```ruby
|
111
210
|
class AddAvatarColumnsToUsers < ActiveRecord::Migration
|
112
|
-
def
|
211
|
+
def up
|
113
212
|
add_attachment :users, :avatar
|
114
213
|
end
|
115
214
|
|
116
|
-
def
|
215
|
+
def down
|
117
216
|
remove_attachment :users, :avatar
|
118
217
|
end
|
119
218
|
end
|
120
219
|
```
|
121
220
|
|
122
|
-
(Or you can use migration generator: `rails generate paperclip user avatar`)
|
221
|
+
(Or you can use the Rails migration generator: `rails generate paperclip user avatar`)
|
123
222
|
|
124
|
-
|
223
|
+
### Edit and New Views
|
125
224
|
|
126
225
|
```erb
|
127
|
-
<%= form_for @user, :
|
226
|
+
<%= form_for @user, url: users_path, html: { multipart: true } do |form| %>
|
128
227
|
<%= form.file_field :avatar %>
|
129
228
|
<% end %>
|
130
229
|
```
|
131
230
|
|
132
|
-
|
231
|
+
### Edit and New Views with [Simple Form](https://github.com/plataformatec/simple_form)
|
232
|
+
|
233
|
+
```erb
|
234
|
+
<%= simple_form_for @user, url: users_path do |form| %>
|
235
|
+
<%= form.input :avatar, as: :file %>
|
236
|
+
<% end %>
|
237
|
+
```
|
238
|
+
|
239
|
+
### Controller
|
133
240
|
|
134
241
|
```ruby
|
135
242
|
def create
|
136
|
-
@user = User.create(
|
243
|
+
@user = User.create( user_params )
|
244
|
+
end
|
245
|
+
|
246
|
+
private
|
247
|
+
|
248
|
+
# Use strong_parameters for attribute whitelisting
|
249
|
+
# Be sure to update your create() and update() controller methods.
|
250
|
+
|
251
|
+
def user_params
|
252
|
+
params.require(:user).permit(:avatar)
|
137
253
|
end
|
138
254
|
```
|
139
255
|
|
140
|
-
|
256
|
+
### View Helpers
|
141
257
|
|
142
258
|
```erb
|
143
259
|
<%= image_tag @user.avatar.url %>
|
@@ -145,20 +261,33 @@ In your show view:
|
|
145
261
|
<%= image_tag @user.avatar.url(:thumb) %>
|
146
262
|
```
|
147
263
|
|
148
|
-
|
264
|
+
### Checking a File Exists
|
265
|
+
|
266
|
+
There are two methods for checking if a file exists:
|
267
|
+
|
268
|
+
- `file?` and `present?` checks if the `_file_name` field is populated
|
269
|
+
- `exists?` checks if the file exists (will perform a TCP connection if stored in the cloud)
|
270
|
+
|
271
|
+
Keep this in mind if you are checking if files are present in a loop. The first
|
272
|
+
version is significantly more performant, but has different semantics.
|
273
|
+
|
274
|
+
### Deleting an Attachment
|
275
|
+
|
276
|
+
Set the attribute to `nil` and save.
|
149
277
|
|
150
278
|
```ruby
|
151
279
|
@user.avatar = nil
|
152
280
|
@user.save
|
153
281
|
```
|
282
|
+
---
|
154
283
|
|
155
284
|
Usage
|
156
285
|
-----
|
157
286
|
|
158
|
-
The basics of
|
287
|
+
The basics of Paperclip are quite simple: Declare that your model has an
|
159
288
|
attachment with the `has_attached_file` method, and give it a name.
|
160
289
|
|
161
|
-
Paperclip will wrap up
|
290
|
+
Paperclip will wrap up to four attributes (all prefixed with that attachment's name,
|
162
291
|
so you can have multiple attachments per model if you wish) and give them a
|
163
292
|
friendly front end. These attributes are:
|
164
293
|
|
@@ -167,12 +296,12 @@ friendly front end. These attributes are:
|
|
167
296
|
* `<attachment>_content_type`
|
168
297
|
* `<attachment>_updated_at`
|
169
298
|
|
170
|
-
By default, only `<attachment>_file_name` is required for
|
299
|
+
By default, only `<attachment>_file_name` is required for Paperclip to operate.
|
171
300
|
You'll need to add `<attachment>_content_type` in case you want to use content type
|
172
301
|
validation.
|
173
302
|
|
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).
|
303
|
+
More information about the options passed to `has_attached_file` is available in the
|
304
|
+
documentation of [`Paperclip::ClassMethods`](http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
|
176
305
|
|
177
306
|
Validations
|
178
307
|
-----------
|
@@ -186,8 +315,10 @@ For validations, Paperclip introduces several validators to validate your attach
|
|
186
315
|
Example Usage:
|
187
316
|
|
188
317
|
```ruby
|
189
|
-
validates :avatar, :
|
190
|
-
validates_with AttachmentPresenceValidator, :
|
318
|
+
validates :avatar, attachment_presence: true
|
319
|
+
validates_with AttachmentPresenceValidator, attributes: :avatar
|
320
|
+
validates_with AttachmentSizeValidator, attributes: :avatar, less_than: 1.megabytes
|
321
|
+
|
191
322
|
```
|
192
323
|
|
193
324
|
Validators can also be defined using the old helper style:
|
@@ -205,13 +336,13 @@ validates_attachment_presence :avatar
|
|
205
336
|
Lastly, you can also define multiple validations on a single attachment using `validates_attachment`:
|
206
337
|
|
207
338
|
```ruby
|
208
|
-
validates_attachment :avatar, :
|
209
|
-
:
|
210
|
-
:
|
339
|
+
validates_attachment :avatar, presence: true,
|
340
|
+
content_type: { content_type: "image/jpeg" },
|
341
|
+
size: { in: 0..10.kilobytes }
|
211
342
|
```
|
212
343
|
|
213
|
-
_NOTE: Post
|
214
|
-
according to the validations. Your callbacks and processors will
|
344
|
+
_NOTE: Post-processing will not even **start** if the attachment is not valid
|
345
|
+
according to the validations. Your callbacks and processors will **only** be
|
215
346
|
called with valid attachments._
|
216
347
|
|
217
348
|
```ruby
|
@@ -253,55 +384,138 @@ class BooksController < ApplicationController
|
|
253
384
|
end
|
254
385
|
```
|
255
386
|
|
387
|
+
**A note on content_type validations and security**
|
388
|
+
|
389
|
+
You should ensure that you validate files to be only those MIME types you
|
390
|
+
explicitly want to support. If you don't, you could be open to
|
391
|
+
<a href="https://www.owasp.org/index.php/Testing_for_Stored_Cross_site_scripting_(OWASP-DV-002)">XSS attacks</a>
|
392
|
+
if a user uploads a file with a malicious HTML payload.
|
393
|
+
|
394
|
+
If you're only interested in images, restrict your allowed content_types to
|
395
|
+
image-y ones:
|
396
|
+
|
397
|
+
```ruby
|
398
|
+
validates_attachment :avatar,
|
399
|
+
content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
|
400
|
+
```
|
401
|
+
|
402
|
+
`Paperclip::ContentTypeDetector` will attempt to match a file's extension to an
|
403
|
+
inferred content_type, regardless of the actual contents of the file.
|
404
|
+
|
405
|
+
---
|
406
|
+
|
407
|
+
Internationalization (I18n)
|
408
|
+
---------------------------
|
409
|
+
|
410
|
+
For using or adding locale files in different languages, check the project
|
411
|
+
https://github.com/thoughtbot/paperclip-i18n.
|
412
|
+
|
413
|
+
Security Validations
|
414
|
+
====================
|
415
|
+
|
416
|
+
Thanks to a report from [Egor Homakov](http://homakov.blogspot.com/) we have
|
417
|
+
taken steps to prevent people from spoofing Content-Types and getting data
|
418
|
+
you weren't expecting onto your server.
|
419
|
+
|
420
|
+
NOTE: Starting at version 4.0.0, all attachments are *required* to include a
|
421
|
+
content_type validation, a file_name validation, or to explicitly state that
|
422
|
+
they're not going to have either. *Paperclip will raise an error* if you do not
|
423
|
+
do this.
|
424
|
+
|
425
|
+
```ruby
|
426
|
+
class ActiveRecord::Base
|
427
|
+
has_attached_file :avatar
|
428
|
+
# Validate content type
|
429
|
+
validates_attachment_content_type :avatar, content_type: /\Aimage/
|
430
|
+
# Validate filename
|
431
|
+
validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
|
432
|
+
# Explicitly do not validate
|
433
|
+
do_not_validate_attachment_file_type :avatar
|
434
|
+
end
|
435
|
+
```
|
436
|
+
|
437
|
+
This keeps Paperclip secure-by-default, and will prevent people trying to mess
|
438
|
+
with your filesystem.
|
439
|
+
|
440
|
+
NOTE: Also starting at version 4.0.0, Paperclip has another validation that
|
441
|
+
cannot be turned off. This validation will prevent content type spoofing. That
|
442
|
+
is, uploading a PHP document (for example) as part of the EXIF tags of a
|
443
|
+
well-formed JPEG. This check is limited to the media type (the first part of the
|
444
|
+
MIME type, so, 'text' in `text/plain`). This will prevent HTML documents from
|
445
|
+
being uploaded as JPEGs, but will not prevent GIFs from being uploaded with a
|
446
|
+
`.jpg` extension. This validation will only add validation errors to the form. It
|
447
|
+
will not cause errors to be raised.
|
448
|
+
|
449
|
+
This can sometimes cause false validation errors in applications that use custom
|
450
|
+
file extensions. In these cases you may wish to add your custom extension to the
|
451
|
+
list of content type mappings by creating `config/initializers/paperclip.rb`:
|
452
|
+
|
453
|
+
```ruby
|
454
|
+
# Allow ".foo" as an extension for files with the MIME type "text/plain".
|
455
|
+
Paperclip.options[:content_type_mappings] = {
|
456
|
+
foo: %w(text/plain)
|
457
|
+
}
|
458
|
+
```
|
459
|
+
|
460
|
+
---
|
461
|
+
|
256
462
|
Defaults
|
257
463
|
--------
|
258
|
-
Global defaults for all your
|
464
|
+
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.
|
259
465
|
|
260
|
-
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
|
466
|
+
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:
|
261
467
|
|
262
468
|
```ruby
|
263
469
|
module YourApp
|
264
470
|
class Application < Rails::Application
|
265
471
|
# Other code...
|
266
472
|
|
267
|
-
config.paperclip_defaults = {:
|
473
|
+
config.paperclip_defaults = { storage: :fog, fog_credentials: { provider: "Local", local_root: "#{Rails.root}/public"}, fog_directory: "", fog_host: "localhost"}
|
268
474
|
end
|
269
475
|
end
|
270
476
|
```
|
271
477
|
|
272
|
-
Another option is to directly modify the Paperclip::Attachment.default_options Hash
|
478
|
+
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.
|
273
479
|
|
274
480
|
An example Rails initializer would look something like this:
|
275
481
|
|
276
482
|
```ruby
|
277
483
|
Paperclip::Attachment.default_options[:storage] = :fog
|
278
|
-
Paperclip::Attachment.default_options[:fog_credentials] = {:
|
484
|
+
Paperclip::Attachment.default_options[:fog_credentials] = { provider: "Local", local_root: "#{Rails.root}/public"}
|
279
485
|
Paperclip::Attachment.default_options[:fog_directory] = ""
|
280
486
|
Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"
|
281
487
|
```
|
488
|
+
---
|
282
489
|
|
283
490
|
Migrations
|
284
491
|
----------
|
285
492
|
|
286
|
-
Paperclip defines several migration methods which can be used to create necessary columns in your
|
287
|
-
model. There are two types of
|
493
|
+
Paperclip defines several migration methods which can be used to create the necessary columns in your
|
494
|
+
model. There are two types of helper methods to aid in this, as follows:
|
495
|
+
|
496
|
+
### Add Attachment Column To A Table
|
288
497
|
|
289
|
-
|
498
|
+
The `attachment` helper can be used when creating a table:
|
290
499
|
|
291
500
|
```ruby
|
292
|
-
class
|
293
|
-
def
|
501
|
+
class CreateUsersWithAttachments < ActiveRecord::Migration
|
502
|
+
def up
|
294
503
|
create_table :users do |t|
|
295
504
|
t.attachment :avatar
|
296
505
|
end
|
297
506
|
end
|
507
|
+
|
508
|
+
# This is assuming you are only using the users table for Paperclip attachment. Drop with care!
|
509
|
+
def down
|
510
|
+
drop_table :users
|
511
|
+
end
|
298
512
|
end
|
299
513
|
```
|
300
514
|
|
301
|
-
|
515
|
+
You can also use the `change` method, instead of the `up`/`down` combination above, as shown below:
|
302
516
|
|
303
517
|
```ruby
|
304
|
-
class
|
518
|
+
class CreateUsersWithAttachments < ActiveRecord::Migration
|
305
519
|
def change
|
306
520
|
create_table :users do |t|
|
307
521
|
t.attachment :avatar
|
@@ -312,33 +526,37 @@ end
|
|
312
526
|
|
313
527
|
### Schema Definition
|
314
528
|
|
529
|
+
Alternatively, the `add_attachment` and `remove_attachment` methods can be used to add new Paperclip columns to an existing table:
|
530
|
+
|
315
531
|
```ruby
|
316
|
-
class
|
317
|
-
def
|
532
|
+
class AddAttachmentColumnsToUsers < ActiveRecord::Migration
|
533
|
+
def up
|
318
534
|
add_attachment :users, :avatar
|
319
535
|
end
|
320
536
|
|
321
|
-
def
|
537
|
+
def down
|
322
538
|
remove_attachment :users, :avatar
|
323
539
|
end
|
324
540
|
end
|
325
541
|
```
|
326
542
|
|
327
|
-
|
543
|
+
Or you can do this with the `change` method:
|
328
544
|
|
329
545
|
```ruby
|
330
|
-
class
|
546
|
+
class AddAttachmentColumnsToUsers < ActiveRecord::Migration
|
331
547
|
def change
|
332
548
|
add_attachment :users, :avatar
|
333
549
|
end
|
334
550
|
end
|
335
551
|
```
|
336
552
|
|
337
|
-
### Vintage
|
553
|
+
### Vintage Syntax
|
338
554
|
|
339
|
-
Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`)
|
555
|
+
Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) is still supported in
|
340
556
|
Paperclip 3.x, but you're advised to update those migration files to use this new syntax.
|
341
557
|
|
558
|
+
---
|
559
|
+
|
342
560
|
Storage
|
343
561
|
-------
|
344
562
|
|
@@ -351,6 +569,7 @@ Paperclip ships with 3 storage adapters:
|
|
351
569
|
If you would like to use Paperclip with another storage, you can install these
|
352
570
|
gems along side with Paperclip:
|
353
571
|
|
572
|
+
* [paperclip-azure](https://github.com/supportify/paperclip-azure)
|
354
573
|
* [paperclip-azure-storage](https://github.com/gmontard/paperclip-azure-storage)
|
355
574
|
* [paperclip-dropbox](https://github.com/janko-m/paperclip-dropbox)
|
356
575
|
|
@@ -359,9 +578,9 @@ gems along side with Paperclip:
|
|
359
578
|
The files that are assigned as attachments are, by default, placed in the
|
360
579
|
directory specified by the `:path` option to `has_attached_file`. By default, this
|
361
580
|
location is `:rails_root/public/system/:class/:attachment/:id_partition/:style/:filename`.
|
362
|
-
This location was chosen because on standard Capistrano deployments, the
|
363
|
-
`public/system` directory
|
364
|
-
|
581
|
+
This location was chosen because, on standard Capistrano deployments, the
|
582
|
+
`public/system` directory can be symlinked to the app's shared directory, meaning it
|
583
|
+
survives between deployments. For example, using that `:path`, you may have a
|
365
584
|
file at
|
366
585
|
|
367
586
|
/data/myapp/releases/20081229172410/public/system/users/avatar/000/000/013/small/my_pic.png
|
@@ -373,12 +592,12 @@ You may also choose to store your files using Amazon's S3 service. To do so, inc
|
|
373
592
|
the `aws-sdk` gem in your Gemfile:
|
374
593
|
|
375
594
|
```ruby
|
376
|
-
gem 'aws-sdk', '~>
|
595
|
+
gem 'aws-sdk', '~> 2.3.0'
|
377
596
|
```
|
378
597
|
|
379
598
|
And then you can specify using S3 from `has_attached_file`.
|
380
599
|
You can find more information about configuring and using S3 storage in
|
381
|
-
[the `Paperclip::Storage::S3` documentation](http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
|
600
|
+
[the `Paperclip::Storage::S3` documentation](http://www.rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
|
382
601
|
|
383
602
|
Files on the local filesystem (and in the Rails app's public directory) will be
|
384
603
|
available to the internet at large. If you require access control, it's
|
@@ -387,63 +606,117 @@ both the `:path` and `:url` options in order to make sure the files are unavaila
|
|
387
606
|
to the public. Both `:path` and `:url` allow the same set of interpolated
|
388
607
|
variables.
|
389
608
|
|
609
|
+
---
|
610
|
+
|
611
|
+
IO Adapters
|
612
|
+
-----------
|
613
|
+
|
614
|
+
When a file is uploaded or attached, it can be in one of a few different input
|
615
|
+
forms, from Rails' UploadedFile object to a StringIO to a Tempfile or even a
|
616
|
+
simple String that is a URL that points to an image.
|
617
|
+
|
618
|
+
Paperclip will accept, by default, many of these sources. It also is capable of
|
619
|
+
handling even more with a little configuration. The IO Adapters that handle
|
620
|
+
images from non-local sources are not enabled by default. They can be enabled by
|
621
|
+
adding a line similar to the following into `config/initializers/paperclip.rb`:
|
622
|
+
|
623
|
+
```ruby
|
624
|
+
Paperclip::DataUriAdapter.register
|
625
|
+
```
|
626
|
+
|
627
|
+
It's best to only enable a remote-loading adapter if you need it. Otherwise
|
628
|
+
there's a chance that someone can gain insight into your internal network
|
629
|
+
structure using it as a vector.
|
630
|
+
|
631
|
+
The following adapters are *not* loaded by default:
|
632
|
+
|
633
|
+
* `Paperclip::UriAdapter` - which accepts a `URI` instance.
|
634
|
+
* `Paperclip::HttpUrlProxyAdapter` - which accepts a `http` string.
|
635
|
+
* `Paperclip::DataUriAdapter` - which accepts a Base64-encoded `data:` string.
|
636
|
+
|
637
|
+
---
|
638
|
+
|
390
639
|
Post Processing
|
391
640
|
---------------
|
392
641
|
|
393
642
|
Paperclip supports an extensible selection of post-processors. When you define
|
394
643
|
a set of styles for an attachment, by default it is expected that those
|
395
|
-
"styles" are actually "thumbnails"
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
paperclip, allowing you to easily define custom processors. You can specify a
|
400
|
-
processor with the :processors option to `has_attached_file`:
|
644
|
+
"styles" are actually "thumbnails." These are processed by
|
645
|
+
`Paperclip::Thumbnail`. For backward compatibility reasons you can pass either
|
646
|
+
a single geometry string, or an array containing a geometry and a format that
|
647
|
+
the file will be converted to, like so:
|
401
648
|
|
402
649
|
```ruby
|
403
|
-
has_attached_file :
|
404
|
-
:processors => [:ocr]
|
650
|
+
has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }
|
405
651
|
```
|
406
652
|
|
407
|
-
This
|
408
|
-
|
409
|
-
|
653
|
+
This will convert the "thumb" style to a 32x32 square in PNG format, regardless
|
654
|
+
of what was uploaded. If the format is not specified, it is kept the same (e.g.
|
655
|
+
JPGs will remain JPGs). `Paperclip::Thumbnail` uses ImageMagick to process
|
656
|
+
images; [ImageMagick's geometry documentation](http://www.imagemagick.org/script/command-line-processing.php#geometry)
|
657
|
+
has more information on the accepted style formats.
|
658
|
+
|
659
|
+
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:
|
660
|
+
|
661
|
+
* `MAGICK_MEMORY_LIMIT=128MiB`
|
662
|
+
* `MAGICK_MAP_LIMIT=64MiB`
|
663
|
+
* `MAGICK_TIME_LIMIT=30`
|
664
|
+
|
665
|
+
For a full list of variables and description, see [ImageMagick's resources documentation](http://www.imagemagick.org/script/resources.php).
|
666
|
+
|
667
|
+
---
|
410
668
|
|
411
|
-
|
412
|
-
|
413
|
-
|
669
|
+
Custom Attachment Processors
|
670
|
+
-------
|
671
|
+
|
672
|
+
You can write your own custom attachment processors to carry out tasks like
|
673
|
+
adding watermarks, compressing images, or encrypting files. Custom processors
|
674
|
+
must be defined within the `Paperclip` module, inherit from
|
675
|
+
`Paperclip::Processor` (see [`lib/paperclip/processor.rb`](https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb)),
|
676
|
+
and implement a `make` method that returns a `File`. All files in your Rails
|
677
|
+
app's `lib/paperclip` and `lib/paperclip_processors` directories will be
|
678
|
+
automatically loaded by Paperclip. Processors are specified using the
|
679
|
+
`:processors` option to `has_attached_file`:
|
414
680
|
|
415
681
|
```ruby
|
416
|
-
has_attached_file :
|
682
|
+
has_attached_file :scan, styles: { text: { quality: :better } },
|
683
|
+
processors: [:ocr]
|
417
684
|
```
|
418
685
|
|
419
|
-
This
|
420
|
-
|
421
|
-
jpgs will remain jpgs). For more information on the accepted style formats, see
|
422
|
-
[here](http://www.imagemagick.org/script/command-line-processing.php#geometry).
|
686
|
+
This would load the hypothetical class `Paperclip::Ocr`, and pass it the
|
687
|
+
options hash `{ quality: :better }`, along with the uploaded file.
|
423
688
|
|
424
689
|
Multiple processors can be specified, and they will be invoked in the order
|
425
|
-
they are defined in the
|
426
|
-
|
427
|
-
|
428
|
-
|
690
|
+
they are defined in the `:processors` array. Each successive processor is given
|
691
|
+
the result from the previous processor. All processors receive the same
|
692
|
+
parameters, which are defined in the `:styles` hash. For example, assuming we
|
693
|
+
had this definition:
|
429
694
|
|
430
695
|
```ruby
|
431
|
-
has_attached_file :scan, :
|
432
|
-
:
|
696
|
+
has_attached_file :scan, styles: { text: { quality: :better } },
|
697
|
+
processors: [:rotator, :ocr]
|
433
698
|
```
|
434
699
|
|
435
|
-
|
436
|
-
options
|
437
|
-
|
700
|
+
Both the `:rotator` processor and the `:ocr` processor would receive the
|
701
|
+
options `{ quality: :better }`. If a processor receives an option it doesn't
|
702
|
+
recognise, it's expected to ignore it.
|
438
703
|
|
439
704
|
_NOTE: Because processors operate by turning the original attachment into the
|
440
705
|
styles, no processors will be run if there are no styles defined._
|
441
706
|
|
442
707
|
If you're interested in caching your thumbnail's width, height and size in the
|
443
|
-
database, take a look at the [paperclip-meta](https://github.com/
|
708
|
+
database, take a look at the [paperclip-meta](https://github.com/teeparham/paperclip-meta)
|
709
|
+
gem.
|
444
710
|
|
445
711
|
Also, if you're interested in generating the thumbnail on-the-fly, you might want
|
446
|
-
to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly)
|
712
|
+
to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly)
|
713
|
+
gem.
|
714
|
+
|
715
|
+
Paperclip's thumbnail generator (see [`lib/paperclip/thumbnail.rb`](lib/paperclip/thumbnail.rb))
|
716
|
+
is implemented as a processor, and may be a good reference for writing your own
|
717
|
+
processors.
|
718
|
+
|
719
|
+
---
|
447
720
|
|
448
721
|
Events
|
449
722
|
------
|
@@ -459,8 +732,8 @@ normal ActiveRecord callbacks as possible, so if you return false (specifically
|
|
459
732
|
will halt. Returning false in an `after_filter` will not halt anything, but you
|
460
733
|
can access the model and the attachment if necessary.
|
461
734
|
|
462
|
-
_NOTE: Post processing will not even
|
463
|
-
according to the validations. Your callbacks and processors will
|
735
|
+
_NOTE: Post processing will not even **start** if the attachment is not valid
|
736
|
+
according to the validations. Your callbacks and processors will **only** be
|
464
737
|
called with valid attachments._
|
465
738
|
|
466
739
|
```ruby
|
@@ -475,6 +748,8 @@ class Message < ActiveRecord::Base
|
|
475
748
|
end
|
476
749
|
```
|
477
750
|
|
751
|
+
---
|
752
|
+
|
478
753
|
URI Obfuscation
|
479
754
|
---------------
|
480
755
|
|
@@ -485,8 +760,8 @@ Example Usage:
|
|
485
760
|
|
486
761
|
```ruby
|
487
762
|
has_attached_file :avatar, {
|
488
|
-
:
|
489
|
-
:
|
763
|
+
url: "/system/:hash.:extension",
|
764
|
+
hash_secret: "longSecretString"
|
490
765
|
}
|
491
766
|
```
|
492
767
|
|
@@ -494,46 +769,54 @@ has_attached_file :avatar, {
|
|
494
769
|
The `:hash` interpolation will be replaced with a unique hash made up of whatever
|
495
770
|
is specified in `:hash_data`. The default value for `:hash_data` is `":class/:attachment/:id/:style/:updated_at"`.
|
496
771
|
|
497
|
-
`:hash_secret` is required
|
772
|
+
`:hash_secret` is required - an exception will be raised if `:hash` is used without `:hash_secret` present.
|
498
773
|
|
499
|
-
For more on this feature read the author's own explanation
|
774
|
+
For more on this feature, read [the author's own explanation](https://github.com/thoughtbot/paperclip/pull/416)
|
500
775
|
|
501
|
-
|
776
|
+
Checksum / Fingerprint
|
502
777
|
-------
|
503
778
|
|
504
|
-
A
|
779
|
+
A checksum of the original file assigned will be placed in the model if it
|
505
780
|
has an attribute named fingerprint. Following the user model migration example
|
506
|
-
above, the migration would look like the following
|
781
|
+
above, the migration would look like the following:
|
507
782
|
|
508
783
|
```ruby
|
509
784
|
class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
|
510
|
-
def
|
785
|
+
def up
|
511
786
|
add_column :users, :avatar_fingerprint, :string
|
512
787
|
end
|
513
788
|
|
514
|
-
def
|
789
|
+
def down
|
515
790
|
remove_column :users, :avatar_fingerprint
|
516
791
|
end
|
517
792
|
end
|
518
793
|
```
|
519
794
|
|
520
|
-
|
795
|
+
The algorithm can be specified using a configuration option; it defaults to MD5
|
796
|
+
for backwards compatibility with Paperclip 5 and earlier.
|
797
|
+
|
798
|
+
```ruby
|
799
|
+
has_attached_file :some_attachment, adapter_options: { hash_digest: Digest::SHA256 }
|
800
|
+
```
|
801
|
+
|
802
|
+
Run `CLASS=User ATTACHMENT=avatar rake paperclip:refresh:fingerprints` after
|
803
|
+
changing the digest on existing attachments to update the fingerprints in the
|
804
|
+
database.
|
805
|
+
|
806
|
+
File Preservation for Soft-Delete
|
521
807
|
-------
|
522
808
|
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
an image using imagemagick's `composite` command. Following the
|
533
|
-
implementation pattern of the thumbnail processor would be a way to implement a
|
534
|
-
watermark processor. All kinds of attachment processors can be created;
|
535
|
-
a few utility examples would be compression and encryption processors.
|
809
|
+
An option is available to preserve attachments in order to play nicely with soft-deleted models. (acts_as_paranoid, paranoia, etc.)
|
810
|
+
|
811
|
+
```ruby
|
812
|
+
has_attached_file :some_attachment, {
|
813
|
+
preserve_files: true,
|
814
|
+
}
|
815
|
+
```
|
816
|
+
|
817
|
+
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.
|
536
818
|
|
819
|
+
---
|
537
820
|
|
538
821
|
Dynamic Configuration
|
539
822
|
---------------------
|
@@ -548,7 +831,7 @@ instances.
|
|
548
831
|
### Dynamic Styles:
|
549
832
|
|
550
833
|
Imagine a user model that had different styles based on the role of the user.
|
551
|
-
Perhaps some users are bosses (e.g. a User model instance responds to
|
834
|
+
Perhaps some users are bosses (e.g. a User model instance responds to `#boss?`)
|
552
835
|
and merit a bigger avatar thumbnail than regular users. The configuration to
|
553
836
|
determine what style parameters are to be used based on the user role might
|
554
837
|
look as follows where a boss will receive a `300x300` thumbnail otherwise a
|
@@ -556,7 +839,7 @@ look as follows where a boss will receive a `300x300` thumbnail otherwise a
|
|
556
839
|
|
557
840
|
```ruby
|
558
841
|
class User < ActiveRecord::Base
|
559
|
-
has_attached_file :avatar, :
|
842
|
+
has_attached_file :avatar, styles: lambda { |attachment| { thumb: (attachment.instance.boss? ? "300x300>" : "100x100>") } }
|
560
843
|
end
|
561
844
|
```
|
562
845
|
|
@@ -573,15 +856,17 @@ processors, where a defined `watermark` processor is invoked after the
|
|
573
856
|
|
574
857
|
```ruby
|
575
858
|
class User < ActiveRecord::Base
|
576
|
-
has_attached_file :avatar, :
|
577
|
-
attr_accessor :
|
859
|
+
has_attached_file :avatar, processors: lambda { |instance| instance.processors }
|
860
|
+
attr_accessor :processors
|
578
861
|
end
|
579
862
|
```
|
580
863
|
|
864
|
+
---
|
865
|
+
|
581
866
|
Logging
|
582
867
|
----------
|
583
868
|
|
584
|
-
By default Paperclip outputs logging according to your logger level. If you want to disable logging (e.g. during testing) add this
|
869
|
+
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:
|
585
870
|
```ruby
|
586
871
|
Your::Application.configure do
|
587
872
|
...
|
@@ -590,11 +875,23 @@ Your::Application.configure do
|
|
590
875
|
end
|
591
876
|
```
|
592
877
|
|
593
|
-
More information in the [rdocs](http://
|
878
|
+
More information in the [rdocs](http://www.rubydoc.info/github/thoughtbot/paperclip/Paperclip.options)
|
879
|
+
|
880
|
+
---
|
594
881
|
|
595
882
|
Deployment
|
596
883
|
----------
|
597
884
|
|
885
|
+
To make Capistrano symlink the `public/system` directory so that attachments
|
886
|
+
survive new deployments, set the `linked_dirs` option in your `config/deploy.rb`
|
887
|
+
file:
|
888
|
+
|
889
|
+
```ruby
|
890
|
+
set :linked_dirs, fetch(:linked_dirs, []).push('public/system')
|
891
|
+
```
|
892
|
+
|
893
|
+
### Attachment Styles
|
894
|
+
|
598
895
|
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
|
599
896
|
`rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
|
600
897
|
by default. You can change it by:
|
@@ -606,30 +903,36 @@ Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachment
|
|
606
903
|
Here is an example for Capistrano:
|
607
904
|
|
608
905
|
```ruby
|
609
|
-
namespace :
|
906
|
+
namespace :paperclip do
|
610
907
|
desc "build missing paperclip styles"
|
611
|
-
task :
|
612
|
-
|
908
|
+
task :build_missing_styles do
|
909
|
+
on roles(:app) do
|
910
|
+
within release_path do
|
911
|
+
with rails_env: fetch(:rails_env) do
|
912
|
+
execute :rake, "paperclip:refresh:missing_styles"
|
913
|
+
end
|
914
|
+
end
|
915
|
+
end
|
613
916
|
end
|
614
917
|
end
|
615
918
|
|
616
|
-
after("deploy:
|
919
|
+
after("deploy:compile_assets", "paperclip:build_missing_styles")
|
617
920
|
```
|
618
921
|
|
619
922
|
Now you don't have to remember to refresh thumbnails in production every time you add a new style.
|
620
|
-
Unfortunately it does not work with dynamic styles - it just ignores them.
|
923
|
+
Unfortunately, it does not work with dynamic styles - it just ignores them.
|
621
924
|
|
622
925
|
If you already have a working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
|
623
926
|
Paperclip about existing styles. Simply create a `paperclip_attachments.yml` file by hand. For example:
|
624
927
|
|
625
928
|
```ruby
|
626
929
|
class User < ActiveRecord::Base
|
627
|
-
has_attached_file :avatar, :
|
930
|
+
has_attached_file :avatar, styles: { thumb: 'x100', croppable: '600x600>', big: '1000x1000>' }
|
628
931
|
end
|
629
932
|
|
630
933
|
class Book < ActiveRecord::Base
|
631
|
-
has_attached_file :cover, :
|
632
|
-
has_attached_file :sample, :
|
934
|
+
has_attached_file :cover, styles: { small: 'x100', large: '1000x1000>' }
|
935
|
+
has_attached_file :sample, styles: { thumb: 'x100' }
|
633
936
|
end
|
634
937
|
```
|
635
938
|
|
@@ -650,11 +953,13 @@ Then in `RAILS_ROOT/public/system/paperclip_attachments.yml`:
|
|
650
953
|
- :thumb
|
651
954
|
```
|
652
955
|
|
956
|
+
---
|
957
|
+
|
653
958
|
Testing
|
654
959
|
-------
|
655
960
|
|
656
961
|
Paperclip provides rspec-compatible matchers for testing attachments. See the
|
657
|
-
documentation on [Paperclip::Shoulda::Matchers](http://rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
|
962
|
+
documentation on [Paperclip::Shoulda::Matchers](http://www.rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
|
658
963
|
for more information.
|
659
964
|
|
660
965
|
**Parallel Tests**
|
@@ -673,9 +978,40 @@ else
|
|
673
978
|
end
|
674
979
|
```
|
675
980
|
|
676
|
-
The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or
|
981
|
+
The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or a
|
677
982
|
similar mechanism for whichever parallel testing library you use.
|
678
983
|
|
984
|
+
**Integration Tests**
|
985
|
+
|
986
|
+
Using integration tests with FactoryGirl may save multiple copies of
|
987
|
+
your test files within the app. To avoid this, specify a custom path in
|
988
|
+
the `config/environments/test.rb` like so:
|
989
|
+
|
990
|
+
```ruby
|
991
|
+
Paperclip::Attachment.default_options[:path] = "#{Rails.root}/spec/test_files/:class/:id_partition/:style.:extension"
|
992
|
+
```
|
993
|
+
|
994
|
+
Then, make sure to delete that directory after the test suite runs by adding
|
995
|
+
this to `spec_helper.rb`.
|
996
|
+
|
997
|
+
```ruby
|
998
|
+
config.after(:suite) do
|
999
|
+
FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
|
1000
|
+
end
|
1001
|
+
```
|
1002
|
+
|
1003
|
+
**Example of test configuration with Factory Girl**
|
1004
|
+
|
1005
|
+
|
1006
|
+
```ruby
|
1007
|
+
FactoryGirl.define do
|
1008
|
+
factory :user do
|
1009
|
+
avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") }
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
```
|
1013
|
+
---
|
1014
|
+
|
679
1015
|
Contributing
|
680
1016
|
------------
|
681
1017
|
|
@@ -683,27 +1019,33 @@ If you'd like to contribute a feature or bugfix: Thanks! To make sure your
|
|
683
1019
|
fix/feature has a high chance of being included, please read the following
|
684
1020
|
guidelines:
|
685
1021
|
|
686
|
-
1.
|
687
|
-
post a new [GitHub Issue](http://github.com/thoughtbot/paperclip/issues).
|
1022
|
+
1. Post a [pull request](https://github.com/thoughtbot/paperclip/compare/).
|
688
1023
|
2. Make sure there are tests! We will not accept any patch that is not tested.
|
689
1024
|
It's a rare time when explicit tests aren't needed. If you have questions
|
690
|
-
about writing tests for paperclip, please
|
1025
|
+
about writing tests for paperclip, please open a
|
1026
|
+
[GitHub issue](https://github.com/thoughtbot/paperclip/issues/new).
|
691
1027
|
|
692
|
-
Please see `CONTRIBUTING.md` for more details on contributing and running test.
|
1028
|
+
Please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for more details on contributing and running test.
|
693
1029
|
|
694
|
-
|
1030
|
+
Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/graphs/contributors)!
|
1031
|
+
|
1032
|
+
License
|
695
1033
|
-------
|
696
1034
|
|
697
|
-
|
1035
|
+
Paperclip is Copyright © 2008-2017 thoughtbot, inc. It is free software, and may be
|
1036
|
+
redistributed under the terms specified in the MIT-LICENSE file.
|
698
1037
|
|
699
|
-
|
1038
|
+
About thoughtbot
|
1039
|
+
----------------
|
700
1040
|
|
701
|
-
|
1041
|
+
![thoughtbot](http://presskit.thoughtbot.com/images/thoughtbot-logo-for-readmes.svg)
|
702
1042
|
|
1043
|
+
Paperclip is maintained and funded by thoughtbot.
|
703
1044
|
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
704
1045
|
|
705
|
-
|
706
|
-
|
1046
|
+
We love open source software!
|
1047
|
+
See [our other projects][community] or
|
1048
|
+
[hire us][hire] to design, develop, and grow your product.
|
707
1049
|
|
708
|
-
|
709
|
-
|
1050
|
+
[community]: https://thoughtbot.com/community?utm_source=github
|
1051
|
+
[hire]: https://thoughtbot.com?utm_source=github
|