paperclip 4.2.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +1066 -0
  3. data/.rubocop.yml +1 -0
  4. data/.travis.yml +18 -15
  5. data/Appraisals +20 -12
  6. data/CONTRIBUTING.md +19 -8
  7. data/Gemfile +4 -9
  8. data/LICENSE +1 -1
  9. data/NEWS +101 -31
  10. data/README.md +243 -159
  11. data/RELEASING.md +17 -0
  12. data/Rakefile +1 -1
  13. data/UPGRADING +12 -9
  14. data/features/basic_integration.feature +8 -4
  15. data/features/migration.feature +0 -24
  16. data/features/step_definitions/attachment_steps.rb +27 -21
  17. data/features/step_definitions/html_steps.rb +2 -2
  18. data/features/step_definitions/rails_steps.rb +11 -17
  19. data/features/step_definitions/s3_steps.rb +2 -2
  20. data/features/step_definitions/web_steps.rb +1 -103
  21. data/features/support/file_helpers.rb +2 -2
  22. data/gemfiles/4.2.awsv2.0.gemfile +17 -0
  23. data/gemfiles/4.2.awsv2.1.gemfile +17 -0
  24. data/gemfiles/{4.1.gemfile → 4.2.awsv2.gemfile} +4 -3
  25. data/gemfiles/5.0.awsv2.0.gemfile +17 -0
  26. data/gemfiles/5.0.awsv2.1.gemfile +17 -0
  27. data/gemfiles/{4.2.gemfile → 5.0.awsv2.gemfile} +4 -3
  28. data/lib/paperclip/attachment.rb +19 -16
  29. data/lib/paperclip/attachment_registry.rb +3 -2
  30. data/lib/paperclip/callbacks.rb +8 -6
  31. data/lib/paperclip/content_type_detector.rb +27 -11
  32. data/lib/paperclip/errors.rb +3 -1
  33. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  34. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  35. data/lib/paperclip/glue.rb +1 -1
  36. data/lib/paperclip/has_attached_file.rb +9 -2
  37. data/lib/paperclip/helpers.rb +14 -10
  38. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  39. data/lib/paperclip/interpolations.rb +18 -13
  40. data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -0
  41. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
  42. data/lib/paperclip/io_adapters/uri_adapter.rb +3 -1
  43. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  44. data/lib/paperclip/media_type_spoof_detector.rb +2 -2
  45. data/lib/paperclip/rails_environment.rb +25 -0
  46. data/lib/paperclip/schema.rb +3 -9
  47. data/lib/paperclip/storage/fog.rb +21 -12
  48. data/lib/paperclip/storage/s3.rb +51 -50
  49. data/lib/paperclip/thumbnail.rb +2 -3
  50. data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
  51. data/lib/paperclip/version.rb +3 -1
  52. data/lib/paperclip.rb +15 -4
  53. data/lib/tasks/paperclip.rake +17 -1
  54. data/paperclip.gemspec +18 -15
  55. data/spec/paperclip/attachment_definitions_spec.rb +1 -1
  56. data/spec/paperclip/attachment_processing_spec.rb +2 -4
  57. data/spec/paperclip/attachment_registry_spec.rb +84 -13
  58. data/spec/paperclip/attachment_spec.rb +91 -31
  59. data/spec/paperclip/content_type_detector_spec.rb +8 -1
  60. data/spec/paperclip/file_command_content_type_detector_spec.rb +0 -1
  61. data/spec/paperclip/geometry_spec.rb +1 -1
  62. data/spec/paperclip/glue_spec.rb +44 -0
  63. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  64. data/spec/paperclip/integration_spec.rb +4 -3
  65. data/spec/paperclip/interpolations_spec.rb +16 -13
  66. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +2 -1
  67. data/spec/paperclip/io_adapters/file_adapter_spec.rb +4 -1
  68. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +12 -0
  69. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +4 -0
  70. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +27 -0
  71. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
  72. data/spec/paperclip/media_type_spoof_detector_spec.rb +34 -11
  73. data/spec/paperclip/paperclip_spec.rb +4 -29
  74. data/spec/paperclip/plural_cache_spec.rb +17 -16
  75. data/spec/paperclip/rails_environment_spec.rb +33 -0
  76. data/spec/paperclip/storage/fog_spec.rb +42 -3
  77. data/spec/paperclip/storage/s3_live_spec.rb +8 -4
  78. data/spec/paperclip/storage/s3_spec.rb +255 -180
  79. data/spec/paperclip/tempfile_factory_spec.rb +4 -0
  80. data/spec/paperclip/thumbnail_spec.rb +16 -0
  81. data/spec/paperclip/url_generator_spec.rb +1 -1
  82. data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
  83. data/spec/paperclip/validators_spec.rb +3 -3
  84. data/spec/spec_helper.rb +6 -1
  85. data/spec/support/assertions.rb +7 -0
  86. data/spec/support/fake_model.rb +4 -0
  87. data/spec/support/fixtures/empty.xlsx +0 -0
  88. data/spec/support/matchers/have_column.rb +11 -2
  89. data/spec/support/model_reconstruction.rb +9 -1
  90. data/spec/support/reporting.rb +11 -0
  91. metadata +105 -54
  92. data/RUNNING_TESTS.md +0 -4
  93. data/cucumber/paperclip_steps.rb +0 -6
  94. data/gemfiles/3.2.gemfile +0 -19
  95. data/gemfiles/4.0.gemfile +0 -19
  96. data/lib/paperclip/locales/de.yml +0 -18
  97. data/lib/paperclip/locales/es.yml +0 -18
  98. data/lib/paperclip/locales/ja.yml +0 -18
  99. data/lib/paperclip/locales/pt-BR.yml +0 -18
  100. data/lib/paperclip/locales/zh-CN.yml +0 -18
  101. data/lib/paperclip/locales/zh-HK.yml +0 -18
  102. data/lib/paperclip/locales/zh-TW.yml +0 -18
  103. data/spec/support/mock_model.rb +0 -2
  104. data/spec/support/rails_helpers.rb +0 -7
data/README.md CHANGED
@@ -1,9 +1,67 @@
1
1
  Paperclip
2
2
  =========
3
3
 
4
- [![Build Status](https://secure.travis-ci.org/thoughtbot/paperclip.png?branch=master)](http://travis-ci.org/thoughtbot/paperclip) [![Dependency Status](https://gemnasium.com/thoughtbot/paperclip.png?travis)](https://gemnasium.com/thoughtbot/paperclip) [![Code Climate](https://codeclimate.com/github/thoughtbot/paperclip.png)](https://codeclimate.com/github/thoughtbot/paperclip) [![Inline docs](http://inch-ci.org/github/thoughtbot/paperclip.png)](http://inch-ci.org/github/thoughtbot/paperclip) [![Security](https://hakiri.io/github/thoughtbot/paperclip/master.svg)](https://hakiri.io/github/thoughtbot/paperclip/master)
4
+ ## Documentation valid for `master` branch
5
5
 
6
- Paperclip is intended as an easy file attachment library for Active Record. The
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
+
21
+ - [Requirements](#requirements)
22
+ - [Ruby and Rails](#ruby-and-rails)
23
+ - [Image Processor](#image-processor)
24
+ - [`file`](#file)
25
+ - [Installation](#installation)
26
+ - [Quick Start](#quick-start)
27
+ - [Models](#models)
28
+ - [Migrations](#migrations)
29
+ - [Edit and New Views](#edit-and-new-views)
30
+ - [Edit and New Views with Simple Form](#edit-and-new-views-with-simple-form)
31
+ - [Controller](#controller)
32
+ - [View Helpers](#view-helpers)
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
+ - [Post Processing](#post-processing)
46
+ - [Events](#events)
47
+ - [URI Obfuscation](#uri-obfuscation)
48
+ - [MD5 Checksum / Fingerprint](#md5-checksum--fingerprint)
49
+ - [File Preservation for Soft-Delete](#file-preservation-for-soft-delete)
50
+ - [Custom Attachment Processors](#custom-attachment-processors)
51
+ - [Dynamic Configuration](#dynamic-configuration)
52
+ - [Dynamic Styles:](#dynamic-styles)
53
+ - [Dynamic Processors:](#dynamic-processors)
54
+ - [Logging](#logging)
55
+ - [Deployment](#deployment)
56
+ - [Attachment Styles](#attachment-styles)
57
+ - [Testing](#testing)
58
+ - [Contributing](#contributing)
59
+ - [License](#license)
60
+ - [About thoughtbot](#about-thoughtbot)
61
+
62
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
63
+
64
+ Paperclip is intended as an easy file attachment library for ActiveRecord. The
7
65
  intent behind it was to keep setup as easy as possible and to treat files as
8
66
  much like other attributes as possible. This means they aren't saved to their
9
67
  final locations on disk, nor are they deleted if set to nil, until
@@ -15,10 +73,10 @@ packages). Attached files are saved to the filesystem and referenced in the
15
73
  browser by an easily understandable specification, which has sensible and
16
74
  useful defaults.
17
75
 
18
- See the documentation for `has_attached_file` in [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods) for
76
+ See the documentation for `has_attached_file` in [`Paperclip::ClassMethods`](http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods) for
19
77
  more detailed options.
20
78
 
21
- The complete [RDoc](http://rdoc.info/gems/paperclip) is online.
79
+ The complete [RDoc](http://www.rubydoc.info/gems/paperclip) is online.
22
80
 
23
81
  ---
24
82
 
@@ -27,9 +85,8 @@ Requirements
27
85
 
28
86
  ### Ruby and Rails
29
87
 
30
- Paperclip now requires Ruby version **>= 1.9.2** and Rails version **>= 3.0** (Only if you're going to use Paperclip with Ruby on Rails.)
31
-
32
- 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.
88
+ Paperclip now requires Ruby version **>= 2.1** and Rails version **>= 4.2**
89
+ (only if you're going to use Paperclip with Ruby on Rails.)
33
90
 
34
91
  ### Image Processor
35
92
 
@@ -47,20 +104,25 @@ In development mode, you might add this line to `config/environments/development
47
104
  Paperclip.options[:command_path] = "/usr/local/bin/"
48
105
  ```
49
106
 
50
- If you're on Mac OS X, you'll want to run the following with Homebrew:
107
+ If you're on Mac OS X, you'll want to run the following with [Homebrew] (http://www.brew.sh):
51
108
 
52
109
  brew install imagemagick
53
110
 
54
111
  If you are dealing with pdf uploads or running the test suite, you'll also need
55
- GhostScript to be installed. On Mac OS X, you can also install that using Homebrew:
112
+ to install GhostScript. On Mac OS X, you can also install that using Homebrew:
56
113
 
57
114
  brew install gs
58
115
 
116
+ If you are on Ubuntu (or any Debian base Linux distribution), you'll want to run
117
+ the following with apt-get:
118
+
119
+ sudo apt-get install imagemagick -y
120
+
59
121
  ### `file`
60
122
 
61
- The Unix [`file` command](http://en.wikipedia.org/wiki/File_(command)) is required for content type checking.
62
- This utility isn't available in Windows, but comes bundled with Ruby [Devkit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit),
63
- so Windows users must make sure that the devkit is installed and added to system `PATH`.
123
+ The Unix [`file` command](https://en.wikipedia.org/wiki/File_(command)) is required for content-type checking.
124
+ This utility isn't available in Windows, but comes bundled with Ruby [Devkit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit),
125
+ so Windows users must make sure that the devkit is installed and added to the system `PATH`.
64
126
 
65
127
  **Manual Installation**
66
128
 
@@ -70,21 +132,21 @@ To manually install, you should perform the following:
70
132
 
71
133
  > **Download & install `file` from [this URL](http://gnuwin32.sourceforge.net/packages/file.htm)**
72
134
 
73
- To test, you can use the following:
135
+ To test, you can use the image below:
74
136
  ![untitled](https://cloud.githubusercontent.com/assets/1104431/4524452/a1f8cce4-4d44-11e4-872e-17adb96f79c9.png)
75
137
 
76
- Next, you need to integrate with your environment - preferrably through the `PATH` variable, or by changing your `config/environments/development.rb` file
138
+ Next, you need to integrate with your environment - preferably through the `PATH` variable, or by changing your `config/environments/development.rb` file
77
139
 
78
140
  **PATH**
79
141
 
80
142
  1. Click "Start"
81
143
  2. On "Computer", right-click and select "Properties"
82
- 3. In properties, select "Advanced System Settings"
144
+ 3. In Properties, select "Advanced System Settings"
83
145
  4. Click the "Environment Variables" button
84
146
  5. Locate the "PATH" var - at the end, add the path to your newly installed `file.exe` (typically `C:\Program Files (x86)\GnuWin32\bin`)
85
147
  6. Restart any CMD shells you have open & see if it works
86
148
 
87
- OR
149
+ OR
88
150
 
89
151
  **Environment**
90
152
 
@@ -92,7 +154,7 @@ OR
92
154
  2. Add the following line: `Paperclip.options[:command_path] = 'C:\Program Files (x86)\GnuWin32\bin'`
93
155
  3. Restart your Rails server
94
156
 
95
- Either of these methods will give your Rails setup access to the `file.exe` functionality, this providing the ability to check the contents of a file (fixing the spoofing problem)
157
+ 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)
96
158
 
97
159
  ---
98
160
 
@@ -104,24 +166,18 @@ Paperclip is distributed as a gem, which is how it should be used in your app.
104
166
  Include the gem in your Gemfile:
105
167
 
106
168
  ```ruby
107
- gem "paperclip", "~> 4.2"
108
- ```
109
-
110
- If you're still using Rails 2.3.x, you should do this instead:
111
-
112
- ```ruby
113
- gem "paperclip", "~> 2.7"
169
+ gem "paperclip", "~> 5.0.0"
114
170
  ```
115
171
 
116
172
  Or, if you want to get the latest, you can get master from the main paperclip repository:
117
173
 
118
174
  ```ruby
119
- gem "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"
175
+ gem "paperclip", git: "git://github.com/thoughtbot/paperclip.git"
120
176
  ```
121
177
 
122
178
  If you're trying to use features that don't seem to be in the latest released gem, but are
123
179
  mentioned in this README, then you probably need to specify the master branch if you want to
124
- use them. This README is probably ahead of the latest released version, if you're reading it
180
+ use them. This README is probably ahead of the latest released version if you're reading it
125
181
  on GitHub.
126
182
 
127
183
  For Non-Rails usage:
@@ -140,22 +196,10 @@ Quick Start
140
196
 
141
197
  ### Models
142
198
 
143
- **Rails 3**
144
-
145
- ```ruby
146
- class User < ActiveRecord::Base
147
- attr_accessible :avatar
148
- has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
149
- validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
150
- end
151
- ```
152
-
153
- **Rails 4**
154
-
155
199
  ```ruby
156
200
  class User < ActiveRecord::Base
157
- has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
158
- validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
201
+ has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
202
+ validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
159
203
  end
160
204
  ```
161
205
 
@@ -163,37 +207,35 @@ end
163
207
 
164
208
  ```ruby
165
209
  class AddAvatarColumnsToUsers < ActiveRecord::Migration
166
- def self.up
210
+ def up
167
211
  add_attachment :users, :avatar
168
212
  end
169
213
 
170
- def self.down
214
+ def down
171
215
  remove_attachment :users, :avatar
172
216
  end
173
217
  end
174
218
  ```
175
219
 
176
- (Or you can use migration generator: `rails generate paperclip user avatar`)
220
+ (Or you can use the Rails migration generator: `rails generate paperclip user avatar`)
177
221
 
178
222
  ### Edit and New Views
179
223
 
180
224
  ```erb
181
- <%= form_for @user, :url => users_path, :html => { :multipart => true } do |form| %>
225
+ <%= form_for @user, url: users_path, html: { multipart: true } do |form| %>
182
226
  <%= form.file_field :avatar %>
183
227
  <% end %>
184
228
  ```
185
229
 
186
- ### Controller
187
-
188
- **Rails 3**
230
+ ### Edit and New Views with [Simple Form](https://github.com/plataformatec/simple_form)
189
231
 
190
- ```ruby
191
- def create
192
- @user = User.create( params[:user] )
193
- end
232
+ ```erb
233
+ <%= simple_form_for @user, url: users_path do |form| %>
234
+ <%= form.input :avatar, as: :file %>
235
+ <% end %>
194
236
  ```
195
237
 
196
- **Rails 4**
238
+ ### Controller
197
239
 
198
240
  ```ruby
199
241
  def create
@@ -210,7 +252,7 @@ def user_params
210
252
  end
211
253
  ```
212
254
 
213
- ### Show View
255
+ ### View Helpers
214
256
 
215
257
  ```erb
216
258
  <%= image_tag @user.avatar.url %>
@@ -231,7 +273,7 @@ Set the attribute to `nil` and save.
231
273
  Usage
232
274
  -----
233
275
 
234
- The basics of paperclip are quite simple: Declare that your model has an
276
+ The basics of Paperclip are quite simple: Declare that your model has an
235
277
  attachment with the `has_attached_file` method, and give it a name.
236
278
 
237
279
  Paperclip will wrap up to four attributes (all prefixed with that attachment's name,
@@ -243,12 +285,12 @@ friendly front end. These attributes are:
243
285
  * `<attachment>_content_type`
244
286
  * `<attachment>_updated_at`
245
287
 
246
- By default, only `<attachment>_file_name` is required for paperclip to operate.
288
+ By default, only `<attachment>_file_name` is required for Paperclip to operate.
247
289
  You'll need to add `<attachment>_content_type` in case you want to use content type
248
290
  validation.
249
291
 
250
- More information about the options to `has_attached_file` is available in the
251
- documentation of [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
292
+ More information about the options passed to `has_attached_file` is available in the
293
+ documentation of [`Paperclip::ClassMethods`](http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
252
294
 
253
295
  Validations
254
296
  -----------
@@ -262,9 +304,9 @@ For validations, Paperclip introduces several validators to validate your attach
262
304
  Example Usage:
263
305
 
264
306
  ```ruby
265
- validates :avatar, :attachment_presence => true
266
- validates_with AttachmentPresenceValidator, :attributes => :avatar
267
- validates_with AttachmentSizeValidator, :attributes => :avatar, :less_than => 1.megabytes
307
+ validates :avatar, attachment_presence: true
308
+ validates_with AttachmentPresenceValidator, attributes: :avatar
309
+ validates_with AttachmentSizeValidator, attributes: :avatar, less_than: 1.megabytes
268
310
 
269
311
  ```
270
312
 
@@ -283,13 +325,13 @@ validates_attachment_presence :avatar
283
325
  Lastly, you can also define multiple validations on a single attachment using `validates_attachment`:
284
326
 
285
327
  ```ruby
286
- validates_attachment :avatar, :presence => true,
287
- :content_type => { :content_type => "image/jpeg" },
288
- :size => { :in => 0..10.kilobytes }
328
+ validates_attachment :avatar, presence: true,
329
+ content_type: { content_type: "image/jpeg" },
330
+ size: { in: 0..10.kilobytes }
289
331
  ```
290
332
 
291
- _NOTE: Post processing will not even *start* if the attachment is not valid
292
- according to the validations. Your callbacks and processors will *only* be
333
+ _NOTE: Post-processing will not even **start** if the attachment is not valid
334
+ according to the validations. Your callbacks and processors will **only** be
293
335
  called with valid attachments._
294
336
 
295
337
  ```ruby
@@ -343,7 +385,7 @@ image-y ones:
343
385
 
344
386
  ```ruby
345
387
  validates_attachment :avatar,
346
- :content_type => { :content_type => ["image/jpeg", "image/gif", "image/png"] }
388
+ content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
347
389
  ```
348
390
 
349
391
  `Paperclip::ContentTypeDetector` will attempt to match a file's extension to an
@@ -351,6 +393,12 @@ inferred content_type, regardless of the actual contents of the file.
351
393
 
352
394
  ---
353
395
 
396
+ Internationalization (I18n)
397
+ ---------------------------
398
+
399
+ For using or adding locale files in different languages, check the project
400
+ https://github.com/thoughtbot/paperclip-i18n.
401
+
354
402
  Security Validations
355
403
  ====================
356
404
 
@@ -367,9 +415,9 @@ do this.
367
415
  class ActiveRecord::Base
368
416
  has_attached_file :avatar
369
417
  # Validate content type
370
- validates_attachment_content_type :avatar, :content_type => /\Aimage/
418
+ validates_attachment_content_type :avatar, content_type: /\Aimage/
371
419
  # Validate filename
372
- validates_attachment_file_name :avatar, :matches => [/png\Z/, /jpe?g\Z/]
420
+ validates_attachment_file_name :avatar, matches: [/png\Z/, /jpe?g\Z/]
373
421
  # Explicitly do not validate
374
422
  do_not_validate_attachment_file_type :avatar
375
423
  end
@@ -382,48 +430,47 @@ NOTE: Also starting at version 4.0.0, Paperclip has another validation that
382
430
  cannot be turned off. This validation will prevent content type spoofing. That
383
431
  is, uploading a PHP document (for example) as part of the EXIF tags of a
384
432
  well-formed JPEG. This check is limited to the media type (the first part of the
385
- MIME type, so, 'text' in 'text/plain'). This will prevent HTML documents from
433
+ MIME type, so, 'text' in `text/plain`). This will prevent HTML documents from
386
434
  being uploaded as JPEGs, but will not prevent GIFs from being uploaded with a
387
- .jpg extension. This validation will only add validation errors to the form. It
388
- will not cause Errors to be raised.
435
+ `.jpg` extension. This validation will only add validation errors to the form. It
436
+ will not cause errors to be raised.
389
437
 
390
- This can sometimes cause false validation errors in applications that use custom
438
+ This can sometimes cause false validation errors in applications that use custom
391
439
  file extensions. In these cases you may wish to add your custom extension to the
392
- list of file extensions allowed for your mime type configured by the mime-types
393
- gem:
440
+ list of content type mappings by creating `config/initializers/paperclip.rb`:
394
441
 
395
442
  ```ruby
396
- # Allow ".foo" as an extension for files with the mime type "text/plain".
397
- text_plain = MIME::Types["text/plain"].first
398
- text_plain.extensions << "foo"
399
- MIME::Types.index_extensions text_plain
443
+ # Allow ".foo" as an extension for files with the MIME type "text/plain".
444
+ Paperclip.options[:content_type_mappings] = {
445
+ foo: %w(text/plain)
446
+ }
400
447
  ```
401
448
 
402
449
  ---
403
450
 
404
451
  Defaults
405
452
  --------
406
- 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.
453
+ 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.
407
454
 
408
- 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:
455
+ 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:
409
456
 
410
457
  ```ruby
411
458
  module YourApp
412
459
  class Application < Rails::Application
413
460
  # Other code...
414
461
 
415
- config.paperclip_defaults = {:storage => :fog, :fog_credentials => {:provider => "Local", :local_root => "#{Rails.root}/public"}, :fog_directory => "", :fog_host => "localhost"}
462
+ config.paperclip_defaults = { storage: :fog, fog_credentials: { provider: "Local", local_root: "#{Rails.root}/public"}, fog_directory: "", fog_host: "localhost"}
416
463
  end
417
464
  end
418
465
  ```
419
466
 
420
- 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.
467
+ 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.
421
468
 
422
469
  An example Rails initializer would look something like this:
423
470
 
424
471
  ```ruby
425
472
  Paperclip::Attachment.default_options[:storage] = :fog
426
- Paperclip::Attachment.default_options[:fog_credentials] = {:provider => "Local", :local_root => "#{Rails.root}/public"}
473
+ Paperclip::Attachment.default_options[:fog_credentials] = { provider: "Local", local_root: "#{Rails.root}/public"}
427
474
  Paperclip::Attachment.default_options[:fog_directory] = ""
428
475
  Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"
429
476
  ```
@@ -432,25 +479,32 @@ Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"
432
479
  Migrations
433
480
  ----------
434
481
 
435
- Paperclip defines several migration methods which can be used to create necessary columns in your
436
- model. There are two types of method:
482
+ Paperclip defines several migration methods which can be used to create the necessary columns in your
483
+ model. There are two types of helper methods to aid in this, as follows:
437
484
 
438
- ### Table Definition
485
+ ### Add Attachment Column To A Table
486
+
487
+ The `attachment` helper can be used when creating a table:
439
488
 
440
489
  ```ruby
441
- class AddAttachmentToUsers < ActiveRecord::Migration
442
- def self.up
490
+ class CreateUsersWithAttachments < ActiveRecord::Migration
491
+ def up
443
492
  create_table :users do |t|
444
493
  t.attachment :avatar
445
494
  end
446
495
  end
496
+
497
+ # This is assuming you are only using the users table for Paperclip attachment. Drop with care!
498
+ def down
499
+ drop_table :users
500
+ end
447
501
  end
448
502
  ```
449
503
 
450
- If you're using Rails 3.2 or newer, this method works in `change` method as well:
504
+ You can also use the `change` method, instead of the `up`/`down` combination above, as shown below:
451
505
 
452
506
  ```ruby
453
- class AddAttachmentToUsers < ActiveRecord::Migration
507
+ class CreateUsersWithAttachments < ActiveRecord::Migration
454
508
  def change
455
509
  create_table :users do |t|
456
510
  t.attachment :avatar
@@ -461,22 +515,24 @@ end
461
515
 
462
516
  ### Schema Definition
463
517
 
518
+ Alternatively, the `add_attachment` and `remove_attachment` methods can be used to add new Paperclip columns to an existing table:
519
+
464
520
  ```ruby
465
- class AddAttachmentToUsers < ActiveRecord::Migration
466
- def self.up
521
+ class AddAttachmentColumnsToUsers < ActiveRecord::Migration
522
+ def up
467
523
  add_attachment :users, :avatar
468
524
  end
469
525
 
470
- def self.down
526
+ def down
471
527
  remove_attachment :users, :avatar
472
528
  end
473
529
  end
474
530
  ```
475
531
 
476
- If you're using Rails 3.2 or newer, you only need `add_attachment` in your `change` method:
532
+ Or you can do this with the `change` method:
477
533
 
478
534
  ```ruby
479
- class AddAttachmentToUsers < ActiveRecord::Migration
535
+ class AddAttachmentColumnsToUsers < ActiveRecord::Migration
480
536
  def change
481
537
  add_attachment :users, :avatar
482
538
  end
@@ -485,7 +541,7 @@ end
485
541
 
486
542
  ### Vintage syntax
487
543
 
488
- Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) are still supported in
544
+ Vintage syntax (such as `t.has_attached_file` and `drop_attached_file`) is still supported in
489
545
  Paperclip 3.x, but you're advised to update those migration files to use this new syntax.
490
546
 
491
547
  ---
@@ -510,9 +566,9 @@ gems along side with Paperclip:
510
566
  The files that are assigned as attachments are, by default, placed in the
511
567
  directory specified by the `:path` option to `has_attached_file`. By default, this
512
568
  location is `:rails_root/public/system/:class/:attachment/:id_partition/:style/:filename`.
513
- This location was chosen because on standard Capistrano deployments, the
514
- `public/system` directory is symlinked to the app's shared directory, meaning it
515
- will survive between deployments. For example, using that `:path`, you may have a
569
+ This location was chosen because, on standard Capistrano deployments, the
570
+ `public/system` directory can be symlinked to the app's shared directory, meaning it
571
+ survives between deployments. For example, using that `:path`, you may have a
516
572
  file at
517
573
 
518
574
  /data/myapp/releases/20081229172410/public/system/users/avatar/000/000/013/small/my_pic.png
@@ -524,12 +580,12 @@ You may also choose to store your files using Amazon's S3 service. To do so, inc
524
580
  the `aws-sdk` gem in your Gemfile:
525
581
 
526
582
  ```ruby
527
- gem 'aws-sdk', '~> 1.5.7'
583
+ gem 'aws-sdk', '>= 2.0.34'
528
584
  ```
529
585
 
530
586
  And then you can specify using S3 from `has_attached_file`.
531
587
  You can find more information about configuring and using S3 storage in
532
- [the `Paperclip::Storage::S3` documentation](http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
588
+ [the `Paperclip::Storage::S3` documentation](http://www.rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
533
589
 
534
590
  Files on the local filesystem (and in the Rails app's public directory) will be
535
591
  available to the internet at large. If you require access control, it's
@@ -545,49 +601,50 @@ Post Processing
545
601
 
546
602
  Paperclip supports an extensible selection of post-processors. When you define
547
603
  a set of styles for an attachment, by default it is expected that those
548
- "styles" are actually "thumbnails". However, you can do much more than just
604
+ "styles" are actually "thumbnails." However, you can do much more than just
549
605
  thumbnail images. By defining a subclass of Paperclip::Processor, you can
550
606
  perform any processing you want on the files that are attached. Any file in
551
607
  your Rails app's `lib/paperclip` and `lib/paperclip_processors` directories is
552
- automatically loaded by paperclip, allowing you to easily define custom
553
- processors. You can specify a processor with the :processors option to
608
+ automatically loaded by Paperclip, allowing you to easily define custom
609
+ processors. You can specify a processor with the `:processors` option to
554
610
  `has_attached_file`:
555
611
 
556
612
  ```ruby
557
- has_attached_file :scan, :styles => { :text => { :quality => :better } },
558
- :processors => [:ocr]
613
+ has_attached_file :scan, styles: { text: { quality: :better } },
614
+ processors: [:ocr]
559
615
  ```
560
616
 
561
617
  This would load the hypothetical class Paperclip::Ocr, which would have the
562
- hash "{ :quality => :better }" passed to it along with the uploaded file. For
563
- more information about defining processors, see Paperclip::Processor.
618
+ hash "{ quality: :better }" passed to it along with the uploaded file. For
619
+ more information about defining processors, see
620
+ [Paperclip::Processor](https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb).
564
621
 
565
- The default processor is Paperclip::Thumbnail. For backwards compatibility
622
+ The default processor is Paperclip::Thumbnail. For backward compatibility
566
623
  reasons, you can pass a single geometry string or an array containing a
567
- geometry and a format, which the file will be converted to, like so:
624
+ geometry and a format that the file will be converted to, like so:
568
625
 
569
626
  ```ruby
570
- has_attached_file :avatar, :styles => { :thumb => ["32x32#", :png] }
627
+ has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }
571
628
  ```
572
629
 
573
- This will convert the "thumb" style to a 32x32 square in png format, regardless
630
+ This will convert the "thumb" style to a 32x32 square in PNG format, regardless
574
631
  of what was uploaded. If the format is not specified, it is kept the same (i.e.
575
- jpgs will remain jpgs). For more information on the accepted style formats, see
632
+ JPGs will remain JPGs). For more information on the accepted style formats, see
576
633
  [here](http://www.imagemagick.org/script/command-line-processing.php#geometry).
577
634
 
578
635
  Multiple processors can be specified, and they will be invoked in the order
579
- they are defined in the :processors array. Each successive processor will
636
+ they are defined in the `:processors` array. Each successive processor will
580
637
  be given the result of the previous processor's execution. All processors will
581
- receive the same parameters, which are what you define in the :styles hash.
638
+ receive the same parameters, which are defined in the `:styles` hash.
582
639
  For example, assuming we had this definition:
583
640
 
584
641
  ```ruby
585
- has_attached_file :scan, :styles => { :text => { :quality => :better } },
586
- :processors => [:rotator, :ocr]
642
+ has_attached_file :scan, styles: { text: { quality: :better } },
643
+ processors: [:rotator, :ocr]
587
644
  ```
588
645
 
589
646
  then both the :rotator processor and the :ocr processor would receive the
590
- options "{ :quality => :better }". This parameter may not mean anything to one
647
+ options `{ quality: :better }`. This parameter may not mean anything to one
591
648
  or more or the processors, and they are expected to ignore it.
592
649
 
593
650
  _NOTE: Because processors operate by turning the original attachment into the
@@ -615,8 +672,8 @@ normal ActiveRecord callbacks as possible, so if you return false (specifically
615
672
  will halt. Returning false in an `after_filter` will not halt anything, but you
616
673
  can access the model and the attachment if necessary.
617
674
 
618
- _NOTE: Post processing will not even *start* if the attachment is not valid
619
- according to the validations. Your callbacks and processors will *only* be
675
+ _NOTE: Post processing will not even **start** if the attachment is not valid
676
+ according to the validations. Your callbacks and processors will **only** be
620
677
  called with valid attachments._
621
678
 
622
679
  ```ruby
@@ -643,8 +700,8 @@ Example Usage:
643
700
 
644
701
  ```ruby
645
702
  has_attached_file :avatar, {
646
- :url => "/system/:hash.:extension",
647
- :hash_secret => "longSecretString"
703
+ url: "/system/:hash.:extension",
704
+ hash_secret: "longSecretString"
648
705
  }
649
706
  ```
650
707
 
@@ -652,24 +709,24 @@ has_attached_file :avatar, {
652
709
  The `:hash` interpolation will be replaced with a unique hash made up of whatever
653
710
  is specified in `:hash_data`. The default value for `:hash_data` is `":class/:attachment/:id/:style/:updated_at"`.
654
711
 
655
- `:hash_secret` is required, an exception will be raised if `:hash` is used without `:hash_secret` present.
712
+ `:hash_secret` is required - an exception will be raised if `:hash` is used without `:hash_secret` present.
656
713
 
657
- For more on this feature read the author's own explanation. [https://github.com/thoughtbot/paperclip/pull/416](https://github.com/thoughtbot/paperclip/pull/416)
714
+ For more on this feature, read [the author's own explanation](https://github.com/thoughtbot/paperclip/pull/416)
658
715
 
659
716
  MD5 Checksum / Fingerprint
660
717
  -------
661
718
 
662
- A MD5 checksum of the original file assigned will be placed in the model if it
719
+ An MD5 checksum of the original file assigned will be placed in the model if it
663
720
  has an attribute named fingerprint. Following the user model migration example
664
- above, the migration would look like the following.
721
+ above, the migration would look like the following:
665
722
 
666
723
  ```ruby
667
724
  class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
668
- def self.up
725
+ def up
669
726
  add_column :users, :avatar_fingerprint, :string
670
727
  end
671
728
 
672
- def self.down
729
+ def down
673
730
  remove_column :users, :avatar_fingerprint
674
731
  end
675
732
  end
@@ -682,7 +739,7 @@ An option is available to preserve attachments in order to play nicely with soft
682
739
 
683
740
  ```ruby
684
741
  has_attached_file :some_attachment, {
685
- :preserve_files => "true",
742
+ preserve_files: "true",
686
743
  }
687
744
  ```
688
745
 
@@ -698,11 +755,11 @@ to inherit from `Paperclip::Processor` (see `lib/paperclip/processor.rb`).
698
755
  For example, when `:styles` are specified for an image attachment, the
699
756
  thumbnail processor (see `lib/paperclip/thumbnail.rb`) is loaded without having
700
757
  to specify it as a `:processor` parameter to `has_attached_file`. When any
701
- other processor is defined it must be called out in the `:processors`
758
+ other processor is defined, it must be called out in the `:processors`
702
759
  parameter if it is to be applied to the attachment. The thumbnail processor
703
- uses the imagemagick `convert` command to do the work of resizing image
760
+ uses the ImageMagick `convert` command to do the work of resizing image
704
761
  thumbnails. It would be easy to create a custom processor that watermarks
705
- an image using imagemagick's `composite` command. Following the
762
+ an image using ImageMagick's `composite` command. Following the
706
763
  implementation pattern of the thumbnail processor would be a way to implement a
707
764
  watermark processor. All kinds of attachment processors can be created;
708
765
  a few utility examples would be compression and encryption processors.
@@ -722,7 +779,7 @@ instances.
722
779
  ### Dynamic Styles:
723
780
 
724
781
  Imagine a user model that had different styles based on the role of the user.
725
- Perhaps some users are bosses (e.g. a User model instance responds to #boss?)
782
+ Perhaps some users are bosses (e.g. a User model instance responds to `#boss?`)
726
783
  and merit a bigger avatar thumbnail than regular users. The configuration to
727
784
  determine what style parameters are to be used based on the user role might
728
785
  look as follows where a boss will receive a `300x300` thumbnail otherwise a
@@ -730,7 +787,7 @@ look as follows where a boss will receive a `300x300` thumbnail otherwise a
730
787
 
731
788
  ```ruby
732
789
  class User < ActiveRecord::Base
733
- has_attached_file :avatar, :styles => lambda { |attachment| { :thumb => (attachment.instance.boss? ? "300x300>" : "100x100>") } }
790
+ has_attached_file :avatar, styles: lambda { |attachment| { thumb: (attachment.instance.boss? ? "300x300>" : "100x100>") } }
734
791
  end
735
792
  ```
736
793
 
@@ -747,7 +804,7 @@ processors, where a defined `watermark` processor is invoked after the
747
804
 
748
805
  ```ruby
749
806
  class User < ActiveRecord::Base
750
- has_attached_file :avatar, :processors => lambda { |instance| instance.processors }
807
+ has_attached_file :avatar, processors: lambda { |instance| instance.processors }
751
808
  attr_accessor :processors
752
809
  end
753
810
  ```
@@ -757,7 +814,7 @@ end
757
814
  Logging
758
815
  ----------
759
816
 
760
- By default Paperclip outputs logging according to your logger level. If you want to disable logging (e.g. during testing) add this in to your environment's configuration:
817
+ 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:
761
818
  ```ruby
762
819
  Your::Application.configure do
763
820
  ...
@@ -766,13 +823,23 @@ Your::Application.configure do
766
823
  end
767
824
  ```
768
825
 
769
- More information in the [rdocs](http://rdoc.info/github/thoughtbot/paperclip/Paperclip.options)
826
+ More information in the [rdocs](http://www.rubydoc.info/github/thoughtbot/paperclip/Paperclip.options)
770
827
 
771
828
  ---
772
829
 
773
830
  Deployment
774
831
  ----------
775
832
 
833
+ To make Capistrano symlink the `public/system` directory so that attachments
834
+ survive new deployments, set the `linked_dirs` option in your `config/deploy.rb`
835
+ file:
836
+
837
+ ```ruby
838
+ set :linked_dirs, fetch(:linked_dirs, []).push('public/system')
839
+ ```
840
+
841
+ ### Attachment Styles
842
+
776
843
  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
777
844
  `rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
778
845
  by default. You can change it by:
@@ -784,32 +851,36 @@ Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachment
784
851
  Here is an example for Capistrano:
785
852
 
786
853
  ```ruby
787
- namespace :deploy do
854
+ namespace :paperclip do
788
855
  desc "build missing paperclip styles"
789
- task :build_missing_paperclip_styles do
856
+ task :build_missing_styles do
790
857
  on roles(:app) do
791
- execute "cd #{current_path}; RAILS_ENV=production bundle exec rake paperclip:refresh:missing_styles"
858
+ within release_path do
859
+ with rails_env: fetch(:rails_env) do
860
+ execute :rake, "paperclip:refresh:missing_styles"
861
+ end
862
+ end
792
863
  end
793
864
  end
794
865
  end
795
866
 
796
- after("deploy:compile_assets", "deploy:build_missing_paperclip_styles")
867
+ after("deploy:compile_assets", "paperclip:build_missing_styles")
797
868
  ```
798
869
 
799
870
  Now you don't have to remember to refresh thumbnails in production every time you add a new style.
800
- Unfortunately it does not work with dynamic styles - it just ignores them.
871
+ Unfortunately, it does not work with dynamic styles - it just ignores them.
801
872
 
802
873
  If you already have a working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
803
874
  Paperclip about existing styles. Simply create a `paperclip_attachments.yml` file by hand. For example:
804
875
 
805
876
  ```ruby
806
877
  class User < ActiveRecord::Base
807
- has_attached_file :avatar, :styles => {:thumb => 'x100', :croppable => '600x600>', :big => '1000x1000>'}
878
+ has_attached_file :avatar, styles: { thumb: 'x100', croppable: '600x600>', big: '1000x1000>' }
808
879
  end
809
880
 
810
881
  class Book < ActiveRecord::Base
811
- has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
812
- has_attached_file :sample, :styles => {:thumb => 'x100'}
882
+ has_attached_file :cover, styles: { small: 'x100', large: '1000x1000>' }
883
+ has_attached_file :sample, styles: { thumb: 'x100' }
813
884
  end
814
885
  ```
815
886
 
@@ -836,7 +907,7 @@ Testing
836
907
  -------
837
908
 
838
909
  Paperclip provides rspec-compatible matchers for testing attachments. See the
839
- documentation on [Paperclip::Shoulda::Matchers](http://rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
910
+ documentation on [Paperclip::Shoulda::Matchers](http://www.rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
840
911
  for more information.
841
912
 
842
913
  **Parallel Tests**
@@ -855,7 +926,7 @@ else
855
926
  end
856
927
  ```
857
928
 
858
- The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or the
929
+ The important part here being the inclusion of `ENV['TEST_ENV_NUMBER']`, or a
859
930
  similar mechanism for whichever parallel testing library you use.
860
931
 
861
932
  **Integration Tests**
@@ -876,6 +947,17 @@ config.after(:suite) do
876
947
  FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
877
948
  end
878
949
  ```
950
+
951
+ **Example of test configuration with Factory Girl**
952
+
953
+
954
+ ```ruby
955
+ FactoryGirl.define do
956
+ factory :user do
957
+ avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") }
958
+ end
959
+ end
960
+ ```
879
961
  ---
880
962
 
881
963
  Contributing
@@ -891,25 +973,27 @@ guidelines:
891
973
  about writing tests for paperclip, please open a
892
974
  [GitHub issue](https://github.com/thoughtbot/paperclip/issues/new).
893
975
 
894
- Please see `CONTRIBUTING.md` for more details on contributing and running test.
976
+ Please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for more details on contributing and running test.
895
977
 
896
- ---
978
+ Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/graphs/contributors)!
897
979
 
898
- Credits
980
+ License
899
981
  -------
900
982
 
901
- ![thoughtbot](http://thoughtbot.com/logo.png)
983
+ Paperclip is Copyright © 2008-2016 thoughtbot, inc. It is free software, and may be
984
+ redistributed under the terms specified in the MIT-LICENSE file.
902
985
 
903
- Paperclip is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
986
+ About thoughtbot
987
+ ----------------
904
988
 
905
- Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/contributors)!
989
+ ![thoughtbot](https://thoughtbot.com/logo.png)
906
990
 
991
+ Paperclip is maintained and funded by thoughtbot.
907
992
  The names and logos for thoughtbot are trademarks of thoughtbot, inc.
908
993
 
909
- ---
910
-
911
- License
912
- -------
994
+ We love open source software!
995
+ See [our other projects][community] or
996
+ [hire us][hire] to design, develop, and grow your product.
913
997
 
914
- Paperclip is Copyright © 2008-2014 thoughtbot, inc. It is free software, and may be
915
- redistributed under the terms specified in the MIT-LICENSE file.
998
+ [community]: https://thoughtbot.com/community?utm_source=github
999
+ [hire]: https://thoughtbot.com?utm_source=github