cloudfuji_paperclip 2.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +13 -0
  3. data/Appraisals +14 -0
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +5 -0
  6. data/Gemfile.lock +137 -0
  7. data/LICENSE +26 -0
  8. data/README.md +444 -0
  9. data/Rakefile +41 -0
  10. data/cucumber/paperclip_steps.rb +6 -0
  11. data/features/basic_integration.feature +46 -0
  12. data/features/rake_tasks.feature +63 -0
  13. data/features/step_definitions/attachment_steps.rb +65 -0
  14. data/features/step_definitions/html_steps.rb +15 -0
  15. data/features/step_definitions/rails_steps.rb +182 -0
  16. data/features/step_definitions/s3_steps.rb +14 -0
  17. data/features/step_definitions/web_steps.rb +209 -0
  18. data/features/support/env.rb +8 -0
  19. data/features/support/fakeweb.rb +3 -0
  20. data/features/support/fixtures/.boot_config.rb.swo +0 -0
  21. data/features/support/fixtures/boot_config.txt +15 -0
  22. data/features/support/fixtures/gemfile.txt +5 -0
  23. data/features/support/fixtures/preinitializer.txt +20 -0
  24. data/features/support/paths.rb +28 -0
  25. data/features/support/rails.rb +46 -0
  26. data/features/support/selectors.rb +19 -0
  27. data/gemfiles/rails2.gemfile +9 -0
  28. data/gemfiles/rails3.gemfile +9 -0
  29. data/gemfiles/rails3_1.gemfile +9 -0
  30. data/generators/paperclip/USAGE +5 -0
  31. data/generators/paperclip/paperclip_generator.rb +27 -0
  32. data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  33. data/init.rb +4 -0
  34. data/lib/generators/paperclip/USAGE +8 -0
  35. data/lib/generators/paperclip/paperclip_generator.rb +33 -0
  36. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  37. data/lib/paperclip/attachment.rb +468 -0
  38. data/lib/paperclip/callback_compatibility.rb +61 -0
  39. data/lib/paperclip/geometry.rb +120 -0
  40. data/lib/paperclip/interpolations.rb +174 -0
  41. data/lib/paperclip/iostream.rb +45 -0
  42. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  43. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +81 -0
  44. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  45. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  46. data/lib/paperclip/matchers.rb +64 -0
  47. data/lib/paperclip/missing_attachment_styles.rb +87 -0
  48. data/lib/paperclip/processor.rb +58 -0
  49. data/lib/paperclip/railtie.rb +31 -0
  50. data/lib/paperclip/schema.rb +39 -0
  51. data/lib/paperclip/storage/filesystem.rb +81 -0
  52. data/lib/paperclip/storage/fog.rb +174 -0
  53. data/lib/paperclip/storage/s3.rb +333 -0
  54. data/lib/paperclip/storage.rb +3 -0
  55. data/lib/paperclip/style.rb +103 -0
  56. data/lib/paperclip/thumbnail.rb +105 -0
  57. data/lib/paperclip/upfile.rb +62 -0
  58. data/lib/paperclip/url_generator.rb +64 -0
  59. data/lib/paperclip/version.rb +3 -0
  60. data/lib/paperclip.rb +487 -0
  61. data/lib/tasks/paperclip.rake +101 -0
  62. data/paperclip.gemspec +41 -0
  63. data/rails/init.rb +2 -0
  64. data/shoulda_macros/paperclip.rb +124 -0
  65. data/test/.gitignore +1 -0
  66. data/test/attachment_test.rb +1116 -0
  67. data/test/database.yml +4 -0
  68. data/test/fixtures/12k.png +0 -0
  69. data/test/fixtures/50x50.png +0 -0
  70. data/test/fixtures/5k.png +0 -0
  71. data/test/fixtures/animated.gif +0 -0
  72. data/test/fixtures/bad.png +1 -0
  73. data/test/fixtures/fog.yml +8 -0
  74. data/test/fixtures/question?mark.png +0 -0
  75. data/test/fixtures/s3.yml +8 -0
  76. data/test/fixtures/spaced file.png +0 -0
  77. data/test/fixtures/text.txt +1 -0
  78. data/test/fixtures/twopage.pdf +0 -0
  79. data/test/fixtures/uppercase.PNG +0 -0
  80. data/test/geometry_test.rb +206 -0
  81. data/test/helper.rb +177 -0
  82. data/test/integration_test.rb +654 -0
  83. data/test/interpolations_test.rb +216 -0
  84. data/test/iostream_test.rb +71 -0
  85. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  86. data/test/matchers/validate_attachment_content_type_matcher_test.rb +87 -0
  87. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  88. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  89. data/test/paperclip_missing_attachment_styles_test.rb +80 -0
  90. data/test/paperclip_test.rb +390 -0
  91. data/test/processor_test.rb +10 -0
  92. data/test/schema_test.rb +98 -0
  93. data/test/storage/filesystem_test.rb +56 -0
  94. data/test/storage/fog_test.rb +219 -0
  95. data/test/storage/s3_live_test.rb +138 -0
  96. data/test/storage/s3_test.rb +943 -0
  97. data/test/style_test.rb +209 -0
  98. data/test/support/mock_attachment.rb +22 -0
  99. data/test/support/mock_interpolator.rb +24 -0
  100. data/test/support/mock_model.rb +2 -0
  101. data/test/support/mock_url_generator_builder.rb +27 -0
  102. data/test/thumbnail_test.rb +383 -0
  103. data/test/upfile_test.rb +53 -0
  104. data/test/url_generator_test.rb +187 -0
  105. metadata +404 -0
data/README.md ADDED
@@ -0,0 +1,444 @@
1
+ Paperclip
2
+ =========
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)
5
+
6
+ Paperclip is intended as an easy file attachment library for Active Record. The
7
+ intent behind it was to keep setup as easy as possible and to treat files as
8
+ much like other attributes as possible. This means they aren't saved to their
9
+ final locations on disk, nor are they deleted if set to nil, until
10
+ ActiveRecord::Base#save is called. It manages validations based on size and
11
+ presence, if required. It can transform its assigned image into thumbnails if
12
+ needed, and the prerequisites are as simple as installing ImageMagick (which,
13
+ for most modern Unix-based systems, is as easy as installing the right
14
+ packages). Attached files are saved to the filesystem and referenced in the
15
+ browser by an easily understandable specification, which has sensible and
16
+ useful defaults.
17
+
18
+ See the documentation for `has_attached_file` in [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods) for
19
+ more detailed options.
20
+
21
+ The complete [RDoc](http://rdoc.info/gems/paperclip) is online.
22
+
23
+
24
+ Requirements
25
+ ------------
26
+
27
+ ImageMagick must be installed and Paperclip must have access to it. To ensure
28
+ that it does, on your command line, run `which convert` (one of the ImageMagick
29
+ utilities). This will give you the path where that utility is installed. For
30
+ example, it might return `/usr/local/bin/convert`.
31
+
32
+ Then, in your environment config file, let Paperclip know to look there by adding that
33
+ directory to its path.
34
+
35
+ In development mode, you might add this line to `config/environments/development.rb)`:
36
+
37
+ Paperclip.options[:command_path] = "/usr/local/bin/"
38
+
39
+ If you're on Mac OS X, you'll want to run the following with Homebrew:
40
+
41
+ brew install imagemagick
42
+
43
+ If you are dealing with pdf uploads or running the test suite, you'll also need
44
+ GhostScript to be installed. On Mac OS X, you can also install that using Homebrew:
45
+
46
+ brew install gs
47
+
48
+
49
+ Installation
50
+ ------------
51
+
52
+ Paperclip is distributed as a gem, which is how it should be used in your app. It's
53
+ technically still installable as a plugin, but that's discouraged, as Rails plays
54
+ well with gems.
55
+
56
+ Include the gem in your Gemfile:
57
+
58
+ gem "paperclip", "~> 2.0"
59
+
60
+ Or, if you want to get the latest, you can get master from the main paperclip repository:
61
+
62
+ gem "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"
63
+
64
+ If you're trying to use features that don't seem to be in the latest released gem, but are
65
+ mentioned in this README, then you probably need to specify the master branch if you want to
66
+ use them. This README is probably ahead of the latest released version, if you're reading it
67
+ on GitHub.
68
+
69
+ Anyway, if you don't use Bundler (though you probably should, even in Rails 2), with config.gem
70
+
71
+ # In config/environment.rb
72
+ ...
73
+ Rails::Initializer.run do |config|
74
+ ...
75
+ config.gem "paperclip", :version => "~> 2.4"
76
+ ...
77
+ end
78
+
79
+ For Non-Rails usage:
80
+
81
+ class ModuleName < ActiveRecord::Base
82
+ include Paperclip::Glue
83
+ ...
84
+ end
85
+
86
+ Quick Start
87
+ -----------
88
+
89
+ In your model:
90
+
91
+ class User < ActiveRecord::Base
92
+ has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }
93
+ end
94
+
95
+ In your migrations:
96
+
97
+ class AddAvatarColumnsToUser < ActiveRecord::Migration
98
+ def self.up
99
+ change_table :users do |t|
100
+ t.has_attached_file :avatar
101
+ end
102
+ end
103
+
104
+ def self.down
105
+ drop_attached_file :users, :avatar
106
+ end
107
+ end
108
+
109
+ In your edit and new views:
110
+
111
+ <%= form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %>
112
+ <%= form.file_field :avatar %>
113
+ <% end %>
114
+
115
+ In your controller:
116
+
117
+ def create
118
+ @user = User.create( params[:user] )
119
+ end
120
+
121
+ In your show view:
122
+
123
+ <%= image_tag @user.avatar.url %>
124
+ <%= image_tag @user.avatar.url(:medium) %>
125
+ <%= image_tag @user.avatar.url(:thumb) %>
126
+
127
+ To detach a file, simply set the attribute to `nil`:
128
+
129
+ @user.avatar = nil
130
+ @user.save
131
+
132
+ Usage
133
+ -----
134
+
135
+ The basics of paperclip are quite simple: Declare that your model has an
136
+ attachment with the `has_attached_file` method, and give it a name.
137
+
138
+ Paperclip will wrap up up to four attributes (all prefixed with that attachment's name,
139
+ so you can have multiple attachments per model if you wish) and give them a
140
+ friendly front end. These attributes are:
141
+
142
+ * `<attachment>_file_name`
143
+ * `<attachment>_file_size`
144
+ * `<attachment>_content_type`
145
+ * `<attachment>_updated_at`
146
+
147
+ By default, only `<attachment>_file_name` is required for paperclip to operate.
148
+ You'll need to add `<attachment>_content_type` in case you want to use content type
149
+ validation.
150
+
151
+ More information about the options to `has_attached_file` is available in the
152
+ documentation of [`Paperclip::ClassMethods`](http://rubydoc.info/gems/paperclip/Paperclip/ClassMethods).
153
+
154
+ For validations, attachments can be validated with these Paperclip's validation methods:
155
+
156
+ * `validates_attachment_presence`
157
+ * `validates_attachment_content_type`
158
+ * `validates_attachment_size`
159
+
160
+ Storage
161
+ -------
162
+
163
+ The files that are assigned as attachments are, by default, placed in the
164
+ directory specified by the `:path` option to `has_attached_file`. By default, this
165
+ location is `:rails_root/public/system/:attachment/:id/:style/:filename`. This
166
+ location was chosen because on standard Capistrano deployments, the
167
+ `public/system` directory is symlinked to the app's shared directory, meaning it
168
+ will survive between deployments. For example, using that `:path`, you may have a
169
+ file at
170
+
171
+ /data/myapp/releases/20081229172410/public/system/avatars/13/small/my_pic.png
172
+
173
+ _**NOTE**: This is a change from previous versions of Paperclip, but is overall a
174
+ safer choice for the default file store._
175
+
176
+ You may also choose to store your files using Amazon's S3 service. To do so, include
177
+ the `aws-sdk` gem in your Gemfile:
178
+
179
+ gem 'aws-sdk'
180
+
181
+ And then you can specify using S3 from `has_attached_file`.
182
+ You can find more information about configuring and using S3 storage in
183
+ [the `Paperclip::Storage::S3` documentation](http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3).
184
+
185
+ Files on the local filesystem (and in the Rails app's public directory) will be
186
+ available to the internet at large. If you require access control, it's
187
+ possible to place your files in a different location. You will need to change
188
+ both the `:path` and `:url` options in order to make sure the files are unavailable
189
+ to the public. Both `:path` and `:url` allow the same set of interpolated
190
+ variables.
191
+
192
+ Post Processing
193
+ ---------------
194
+
195
+ Paperclip supports an extensible selection of post-processors. When you define
196
+ a set of styles for an attachment, by default it is expected that those
197
+ "styles" are actually "thumbnails". However, you can do much more than just
198
+ thumbnail images. By defining a subclass of Paperclip::Processor, you can
199
+ perform any processing you want on the files that are attached. Any file in
200
+ your Rails app's lib/paperclip\_processors directory is automatically loaded by
201
+ paperclip, allowing you to easily define custom processors. You can specify a
202
+ processor with the :processors option to has\_attached\_file:
203
+
204
+ has_attached\_file :scan, :styles => { :text => { :quality => :better } },
205
+ :processors => [:ocr]
206
+
207
+ This would load the hypothetical class Paperclip::Ocr, which would have the
208
+ hash "{ :quality => :better }" passed to it along with the uploaded file. For
209
+ more information about defining processors, see Paperclip::Processor.
210
+
211
+ The default processor is Paperclip::Thumbnail. For backwards compatability
212
+ reasons, you can pass a single geometry string or an array containing a
213
+ geometry and a format, which the file will be converted to, like so:
214
+
215
+ has_attached_file :avatar, :styles => { :thumb => ["32x32#", :png] }
216
+
217
+ This will convert the "thumb" style to a 32x32 square in png format, regardless
218
+ of what was uploaded. If the format is not specified, it is kept the same (i.e.
219
+ jpgs will remain jpgs). For more information on the accepted style formats, see
220
+ [http://www.imagemagick.org/script/command-line-processing.php#geometry](here).
221
+
222
+ Multiple processors can be specified, and they will be invoked in the order
223
+ they are defined in the :processors array. Each successive processor will
224
+ be given the result of the previous processor's execution. All processors will
225
+ receive the same parameters, which are what you define in the :styles hash.
226
+ For example, assuming we had this definition:
227
+
228
+ has_attached_file :scan, :styles => { :text => { :quality => :better } },
229
+ :processors => [:rotator, :ocr]
230
+
231
+ then both the :rotator processor and the :ocr processor would receive the
232
+ options "{ :quality => :better }". This parameter may not mean anything to one
233
+ or more or the processors, and they are expected to ignore it.
234
+
235
+ _NOTE: Because processors operate by turning the original attachment into the
236
+ styles, no processors will be run if there are no styles defined._
237
+
238
+ If you're interested in caching your thumbnail's width, height and size in the
239
+ database, take a look at the [paperclip-meta](https://github.com/y8/paperclip-meta) gem.
240
+
241
+ Also, if you're interested in generating the thumbnail on-the-fly, you might want
242
+ to look into the [attachment_on_the_fly](https://github.com/drpentode/Attachment-on-the-Fly) gem.
243
+
244
+ Events
245
+ ------
246
+
247
+ Before and after the Post Processing step, Paperclip calls back to the model
248
+ with a few callbacks, allowing the model to change or cancel the processing
249
+ step. The callbacks are `before_post_process` and `after_post_process` (which
250
+ are called before and after the processing of each attachment), and the
251
+ attachment-specific `before_<attachment>_post_process` and
252
+ `after_<attachment>_post_process`. The callbacks are intended to be as close to
253
+ normal ActiveRecord callbacks as possible, so if you return false (specifically
254
+ \- returning nil is not the same) in a before\_ filter, the post processing step
255
+ will halt. Returning false in an after\_ filter will not halt anything, but you
256
+ can access the model and the attachment if necessary.
257
+
258
+ _NOTE: Post processing will not even *start* if the attachment is not valid
259
+ according to the validations. Your callbacks and processors will *only* be
260
+ called with valid attachments._
261
+
262
+ URI Obfuscation
263
+ ---------------
264
+
265
+ Paperclip has an interpolation called `:hash` for obfuscating filenames of
266
+ publicly-available files.
267
+
268
+ Example Usage:
269
+
270
+ has_attached_file :avatar, {
271
+ :url => "/system/:hash.:extension",
272
+ :hash_secret => "longSecretString"
273
+ }
274
+
275
+
276
+ The `:hash` interpolation will be replaced with a unique hash made up of whatever
277
+ is specified in `:hash_data`. The default value for `:hash_data` is `":class/:attachment/:id/:style/:updated_at"`.
278
+
279
+ `:hash_secret` is required, an exception will be raised if `:hash` is used without `:hash_secret` present.
280
+
281
+ 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)
282
+
283
+ MD5 Checksum / Fingerprint
284
+ -------
285
+
286
+ A MD5 checksum of the original file assigned will be placed in the model if it
287
+ has an attribute named fingerprint. Following the user model migration example
288
+ above, the migration would look like the following.
289
+
290
+ class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
291
+ def self.up
292
+ add_column :users, :avatar_fingerprint, :string
293
+ end
294
+
295
+ def self.down
296
+ remove_column :users, :avatar_fingerprint
297
+ end
298
+ end
299
+
300
+ Custom Attachment Processors
301
+ -------
302
+
303
+ Custom attachment processors can be implemented and their only requirement is
304
+ to inherit from `Paperclip::Processor` (see `lib/paperclip/processor.rb`).
305
+ For example, when `:styles` are specified for an image attachment, the
306
+ thumbnail processor (see `lib/paperclip/thumbnail.rb`) is loaded without having
307
+ to specify it as a `:processor` parameter to `has_attached_file`. When any
308
+ other processor is defined it must be called out in the `:processors`
309
+ parameter if it is to be applied to the attachment. The thumbnail processor
310
+ uses the imagemagick `convert` command to do the work of resizing image
311
+ thumbnails. It would be easy to create a custom processor that watermarks
312
+ an image using imagemagick's `composite` command. Following the
313
+ implementation pattern of the thumbnail processor would be a way to implement a
314
+ watermark processor. All kinds of attachment processors can be created;
315
+ a few utility examples would be compression and encryption processors.
316
+
317
+
318
+ Dynamic Configuration
319
+ ---------------------
320
+
321
+ Callable objects (lambdas, Procs) can be used in a number of places for dynamic
322
+ configuration throughout Paperclip. This strategy exists in a number of
323
+ components of the library but is most significant in the possibilities for
324
+ allowing custom styles and processors to be applied for specific model
325
+ instances, rather than applying defined styles and processors across all
326
+ instances.
327
+
328
+ Dynamic Styles:
329
+
330
+ Imagine a user model that had different styles based on the role of the user.
331
+ Perhaps some users are bosses (e.g. a User model instance responds to #boss?)
332
+ and merit a bigger avatar thumbnail than regular users. The configuration to
333
+ determine what style parameters are to be used based on the user role might
334
+ look as follows where a boss will receive a `300x300` thumbnail otherwise a
335
+ `100x100` thumbnail will be created.
336
+
337
+ class User < ActiveRecord::Base
338
+ has_attached_file :avatar, :styles => lambda { |attachment| { :thumb => (attachment.instance.boss? ? "300x300>" : "100x100>") }
339
+ end
340
+
341
+ Dynamic Processors:
342
+
343
+ Another contrived example is a user model that is aware of which file processors
344
+ should be applied to it (beyond the implied `thumbnail` processor invoked when
345
+ `:styles` are defined). Perhaps we have a watermark processor available and it is
346
+ only used on the avatars of certain models. The configuration for this might be
347
+ where the instance is queried for which processors should be applied to it.
348
+ Presumably some users might return `[:thumbnail, :watermark]` for its
349
+ processors, where a defined `watermark` processor is invoked after the
350
+ `thumbnail` processor already defined by Paperclip.
351
+
352
+ class User < ActiveRecord::Base
353
+ has_attached_file :avatar, :processors => lambda { |instance| instance.processors }
354
+ attr_accessor :watermark
355
+ end
356
+
357
+ Deploy
358
+ ------
359
+
360
+ Paperclip is aware of new attachment styles you have added in previous deploy. The only thing you should do after each deployment is to call
361
+ `rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
362
+ by default. You can change it by:
363
+
364
+ Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachments.yml'
365
+
366
+ Here is an example for Capistrano:
367
+
368
+ namespace :deploy do
369
+ desc "build missing paperclip styles"
370
+ task :build_missing_paperclip_styles, :roles => :app do
371
+ run "cd #{release_path}; RAILS_ENV=production bundle exec rake paperclip:refresh:missing_styles"
372
+ end
373
+ end
374
+
375
+ after("deploy:update_code", "deploy:build_missing_paperclip_styles")
376
+
377
+ Now you don't have to remember to refresh thumbnails in production everytime you add new style.
378
+ Unfortunately it does not work with dynamic styles - it just ignores them.
379
+
380
+ If you already have working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
381
+ Paperclip about existing styles. Simply create paperclip\_attachments.yml file by hand. For example:
382
+
383
+ class User < ActiveRecord::Base
384
+ has_attached_file :avatar, :styles => {:thumb => 'x100', :croppable => '600x600>', :big => '1000x1000>'}
385
+ end
386
+
387
+ class Book < ActiveRecord::Base
388
+ has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
389
+ has_attached_file :sample, :styles => {:thumb => 'x100'}
390
+ end
391
+
392
+ Then in `RAILS_ROOT/public/system/paperclip_attachments.yml`:
393
+
394
+ ---
395
+ :User:
396
+ :avatar:
397
+ - :thumb
398
+ - :croppable
399
+ - :big
400
+ :Book:
401
+ :cover:
402
+ - :small
403
+ - :large
404
+ :sample:
405
+ - :thumb
406
+
407
+ Testing
408
+ -------
409
+
410
+ Paperclip provides rspec-compatible matchers for testing attachments. See the
411
+ documentation on [Paperclip::Shoulda::Matchers](http://rubydoc.info/gems/paperclip/Paperclip/Shoulda/Matchers)
412
+ for more information.
413
+
414
+ Contributing
415
+ ------------
416
+
417
+ If you'd like to contribute a feature or bugfix: Thanks! To make sure your
418
+ fix/feature has a high chance of being included, please read the following
419
+ guidelines:
420
+
421
+ 1. Ask on the mailing list[http://groups.google.com/group/paperclip-plugin], or
422
+ post a new GitHub Issue[http://github.com/thoughtbot/paperclip/issues].
423
+ 2. Make sure there are tests! We will not accept any patch that is not tested.
424
+ It's a rare time when explicit tests aren't needed. If you have questions
425
+ about writing tests for paperclip, please ask the mailing list.
426
+
427
+ Please see CONTRIBUTING.md for details.
428
+
429
+ Credits
430
+ -------
431
+
432
+ ![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
433
+
434
+ Paperclip is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
435
+
436
+ Thank you to all [the contributors](https://github.com/thoughtbot/paperclip/contributors)!
437
+
438
+ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
439
+
440
+ License
441
+ -------
442
+
443
+ Paperclip is Copyright © 2008-2011 thoughtbot. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
444
+
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'appraisal'
3
+ require 'rake/testtask'
4
+ require 'cucumber/rake/task'
5
+
6
+ desc 'Default: run unit tests.'
7
+ task :default => [:clean, 'appraisal:install', :all]
8
+
9
+ desc 'Test the paperclip plugin under all supported Rails versions.'
10
+ task :all do |t|
11
+ exec('rake appraisal test cucumber')
12
+ end
13
+
14
+ desc 'Test the paperclip plugin.'
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.libs << 'lib' << 'profile'
17
+ t.pattern = 'test/**/*_test.rb'
18
+ t.verbose = true
19
+ end
20
+
21
+ desc 'Run integration test'
22
+ Cucumber::Rake::Task.new do |t|
23
+ t.cucumber_opts = %w{--format progress}
24
+ end
25
+
26
+ desc 'Start an IRB session with all necessary files required.'
27
+ task :shell do |t|
28
+ chdir File.dirname(__FILE__)
29
+ exec 'irb -I lib/ -I lib/paperclip -r rubygems -r active_record -r tempfile -r init'
30
+ end
31
+
32
+ desc 'Clean up files.'
33
+ task :clean do |t|
34
+ FileUtils.rm_rf "doc"
35
+ FileUtils.rm_rf "tmp"
36
+ FileUtils.rm_rf "pkg"
37
+ FileUtils.rm_rf "public"
38
+ FileUtils.rm "test/debug.log" rescue nil
39
+ FileUtils.rm "test/paperclip.db" rescue nil
40
+ Dir.glob("paperclip-*.gem").each{|f| FileUtils.rm f }
41
+ end
@@ -0,0 +1,6 @@
1
+ When /^I attach an? "([^\"]*)" "([^\"]*)" file to an? "([^\"]*)" on S3$/ do |attachment, extension, model|
2
+ stub_paperclip_s3(model, attachment, extension)
3
+ attach_file attachment,
4
+ "features/support/paperclip/#{model.gsub(" ", "_").underscore}/#{attachment}.#{extension}"
5
+ end
6
+
@@ -0,0 +1,46 @@
1
+ Feature: Rails integration
2
+
3
+ Background:
4
+ Given I generate a new rails application
5
+ And I run a rails generator to generate a "User" scaffold with "name:string"
6
+ And I run a paperclip generator to add a paperclip "attachment" to the "User" model
7
+ And I run a migration
8
+ And I update my new user view to include the file upload field
9
+ And I update my user view to include the attachment
10
+
11
+ Scenario: Filesystem integration test
12
+ Given I add this snippet to the User model:
13
+ """
14
+ has_attached_file :attachment
15
+ """
16
+ And I start the rails application
17
+ When I go to the new user page
18
+ And I fill in "Name" with "something"
19
+ And I attach the file "test/fixtures/5k.png" to "Attachment"
20
+ And I press "Submit"
21
+ Then I should see "Name: something"
22
+ And I should see an image with a path of "/system/attachments/1/original/5k.png"
23
+ And the file at "/system/attachments/1/original/5k.png" should be the same as "test/fixtures/5k.png"
24
+
25
+ Scenario: S3 Integration test
26
+ Given I add this snippet to the User model:
27
+ """
28
+ has_attached_file :attachment,
29
+ :storage => :s3,
30
+ :path => "/:attachment/:id/:style/:filename",
31
+ :s3_credentials => Rails.root.join("config/s3.yml")
32
+ """
33
+ And I write to "config/s3.yml" with:
34
+ """
35
+ bucket: paperclip
36
+ access_key_id: access_key
37
+ secret_access_key: secret_key
38
+ """
39
+ And I start the rails application
40
+ When I go to the new user page
41
+ And I fill in "Name" with "something"
42
+ And I attach the file "test/fixtures/5k.png" to "Attachment" on S3
43
+ And I press "Submit"
44
+ Then I should see "Name: something"
45
+ And I should see an image with a path of "http://s3.amazonaws.com/paperclip/attachments/1/original/5k.png"
46
+ And the file at "http://s3.amazonaws.com/paperclip/attachments/1/original/5k.png" should be uploaded to S3
@@ -0,0 +1,63 @@
1
+ Feature: Rake tasks
2
+
3
+ Background:
4
+ Given I generate a new rails application
5
+ And I run a rails generator to generate a "User" scaffold with "name:string"
6
+ And I run a paperclip generator to add a paperclip "attachment" to the "User" model
7
+ And I run a migration
8
+ And I add the paperclip rake task to a Rails 2.3 application
9
+ And I add this snippet to the User model:
10
+ """
11
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename"
12
+ """
13
+
14
+ Scenario: Paperclip refresh thumbnails task
15
+ When I modify my attachment definition to:
16
+ """
17
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename",
18
+ :styles => { :medium => "200x200#" }
19
+ """
20
+ And I upload the fixture "5k.png"
21
+ Then the attachment "medium/5k.png" should have a dimension of 200x200
22
+ When I modify my attachment definition to:
23
+ """
24
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename",
25
+ :styles => { :medium => "100x100#" }
26
+ """
27
+ When I successfully run `bundle exec rake paperclip:refresh:thumbnails CLASS=User --trace`
28
+ Then the attachment "original/5k.png" should exist
29
+ And the attachment "medium/5k.png" should have a dimension of 100x100
30
+
31
+ Scenario: Paperclip refresh metadata task
32
+ When I upload the fixture "5k.png"
33
+ And I swap the attachment "original/5k.png" with the fixture "12k.png"
34
+ And I successfully run `bundle exec rake paperclip:refresh:metadata CLASS=User --trace`
35
+ Then the attachment should have the same content type as the fixture "12k.png"
36
+ And the attachment should have the same file size as the fixture "12k.png"
37
+
38
+ Scenario: Paperclip refresh missing styles task
39
+ When I upload the fixture "5k.png"
40
+ Then the attachment file "original/5k.png" should exist
41
+ And the attachment file "medium/5k.png" should not exist
42
+ When I modify my attachment definition to:
43
+ """
44
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename",
45
+ :styles => { :medium => "200x200#" }
46
+ """
47
+ When I successfully run `bundle exec rake paperclip:refresh:missing_styles --trace`
48
+ Then the attachment file "original/5k.png" should exist
49
+ And the attachment file "medium/5k.png" should exist
50
+
51
+ Scenario: Paperclip clean task
52
+ When I upload the fixture "5k.png"
53
+ And I upload the fixture "12k.png"
54
+ Then the attachment file "original/5k.png" should exist
55
+ And the attachment file "original/12k.png" should exist
56
+ When I modify my attachment definition to:
57
+ """
58
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename"
59
+ validates_attachment_size :attachment, :less_than => 10.kilobytes
60
+ """
61
+ And I successfully run `bundle exec rake paperclip:clean CLASS=User --trace`
62
+ Then the attachment file "original/5k.png" should exist
63
+ But the attachment file "original/12k.png" should not exist
@@ -0,0 +1,65 @@
1
+ module AttachmentHelpers
2
+ def fixture_path(filename)
3
+ File.expand_path("#{PROJECT_ROOT}/test/fixtures/#{filename}")
4
+ end
5
+
6
+ def attachment_path(filename)
7
+ File.expand_path("public/system/attachments/#{filename}")
8
+ end
9
+ end
10
+ World(AttachmentHelpers)
11
+
12
+ When /^I modify my attachment definition to:$/ do |definition|
13
+ write_file "app/models/user.rb", <<-FILE
14
+ class User < ActiveRecord::Base
15
+ #{definition}
16
+ end
17
+ FILE
18
+ in_current_dir { FileUtils.rm_rf ".rbx" }
19
+ end
20
+
21
+ When /^I upload the fixture "([^"]*)"$/ do |filename|
22
+ run_simple %(bundle exec #{runner_command} "User.create!(:attachment => File.open('#{fixture_path(filename)}'))")
23
+ end
24
+
25
+ Then /^the attachment "([^"]*)" should have a dimension of (\d+x\d+)$/ do |filename, dimension|
26
+ in_current_dir do
27
+ geometry = `identify -format "%wx%h" "#{attachment_path(filename)}"`.strip
28
+ geometry.should == dimension
29
+ end
30
+ end
31
+
32
+ Then /^the attachment "([^"]*)" should exist$/ do |filename|
33
+ in_current_dir do
34
+ File.exists?(attachment_path(filename)).should be
35
+ end
36
+ end
37
+
38
+ When /^I swap the attachment "([^"]*)" with the fixture "([^"]*)"$/ do |attachment_filename, fixture_filename|
39
+ in_current_dir do
40
+ require 'fileutils'
41
+ FileUtils.rm_f attachment_path(attachment_filename)
42
+ FileUtils.cp fixture_path(fixture_filename), attachment_path(attachment_filename)
43
+ end
44
+ end
45
+
46
+ Then /^the attachment should have the same content type as the fixture "([^"]*)"$/ do |filename|
47
+ in_current_dir do
48
+ require 'mime/types'
49
+ attachment_content_type = `bundle exec #{runner_command} "puts User.last.attachment_content_type"`.strip
50
+ attachment_content_type.should == MIME::Types.type_for(filename).first.content_type
51
+ end
52
+ end
53
+
54
+ Then /^the attachment should have the same file size as the fixture "([^"]*)"$/ do |filename|
55
+ in_current_dir do
56
+ attachment_file_size = `bundle exec #{runner_command} "puts User.last.attachment_file_size"`.strip
57
+ attachment_file_size.should == File.size(fixture_path(filename)).to_s
58
+ end
59
+ end
60
+
61
+ Then /^the attachment file "([^"]*)" should (not )?exist$/ do |filename, not_exist|
62
+ in_current_dir do
63
+ check_file_presence([attachment_path(filename)], !not_exist)
64
+ end
65
+ end
@@ -0,0 +1,15 @@
1
+ Then %r{I should see an image with a path of "([^"]*)"} do |path|
2
+ page.should have_css("img[src^='#{path}']")
3
+ end
4
+
5
+ Then %r{^the file at "([^"]*)" is the same as "([^"]*)"$} do |web_file, path|
6
+ expected = IO.read(path)
7
+ actual = if web_file.match %r{^https?://}
8
+ Net::HTTP.get(URI.parse(web_file))
9
+ else
10
+ visit(web_file)
11
+ page.body
12
+ end
13
+ actual.force_encoding("UTF-8") if actual.respond_to?(:force_encoding)
14
+ actual.should == expected
15
+ end