paperclip 3.0.4 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Files changed (56) hide show
  1. data/Appraisals +3 -3
  2. data/NEWS +43 -0
  3. data/README.md +81 -5
  4. data/features/basic_integration.feature +20 -2
  5. data/features/migration.feature +94 -0
  6. data/features/step_definitions/attachment_steps.rb +28 -0
  7. data/features/step_definitions/rails_steps.rb +19 -1
  8. data/features/step_definitions/web_steps.rb +3 -3
  9. data/gemfiles/3.0.gemfile +1 -1
  10. data/gemfiles/3.1.gemfile +1 -1
  11. data/gemfiles/3.2.gemfile +1 -1
  12. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +4 -8
  13. data/lib/paperclip.rb +2 -0
  14. data/lib/paperclip/attachment.rb +4 -0
  15. data/lib/paperclip/geometry.rb +33 -0
  16. data/lib/paperclip/glue.rb +2 -1
  17. data/lib/paperclip/io_adapters/abstract_adapter.rb +45 -0
  18. data/lib/paperclip/io_adapters/attachment_adapter.rb +13 -48
  19. data/lib/paperclip/io_adapters/file_adapter.rb +11 -61
  20. data/lib/paperclip/io_adapters/identity_adapter.rb +1 -1
  21. data/lib/paperclip/io_adapters/nil_adapter.rb +1 -1
  22. data/lib/paperclip/io_adapters/stringio_adapter.rb +11 -42
  23. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +6 -45
  24. data/lib/paperclip/matchers.rb +2 -2
  25. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +36 -17
  26. data/lib/paperclip/railtie.rb +5 -1
  27. data/lib/paperclip/schema.rb +59 -23
  28. data/lib/paperclip/storage/filesystem.rb +5 -0
  29. data/lib/paperclip/storage/fog.rb +36 -14
  30. data/lib/paperclip/storage/s3.rb +14 -16
  31. data/lib/paperclip/style.rb +2 -2
  32. data/lib/paperclip/tempfile_factory.rb +21 -0
  33. data/lib/paperclip/thumbnail.rb +10 -1
  34. data/lib/paperclip/version.rb +1 -1
  35. data/paperclip.gemspec +1 -1
  36. data/test/attachment_test.rb +56 -24
  37. data/test/fixtures/animated +0 -0
  38. data/test/fixtures/animated.unknown +0 -0
  39. data/test/generator_test.rb +26 -24
  40. data/test/geometry_test.rb +19 -0
  41. data/test/helper.rb +8 -0
  42. data/test/integration_test.rb +23 -23
  43. data/test/io_adapters/abstract_adapter_test.rb +44 -0
  44. data/test/io_adapters/attachment_adapter_test.rb +96 -34
  45. data/test/io_adapters/file_adapter_test.rb +13 -1
  46. data/test/io_adapters/stringio_adapter_test.rb +9 -10
  47. data/test/io_adapters/uploaded_file_adapter_test.rb +2 -1
  48. data/test/schema_test.rb +179 -77
  49. data/test/storage/filesystem_test.rb +18 -3
  50. data/test/storage/fog_test.rb +64 -1
  51. data/test/storage/s3_test.rb +38 -2
  52. data/test/tempfile_factory_test.rb +13 -0
  53. data/test/thumbnail_test.rb +45 -0
  54. metadata +16 -9
  55. data/features/support/fixtures/.boot_config.rb.swo +0 -0
  56. data/images.rake +0 -21
data/Appraisals CHANGED
@@ -1,14 +1,14 @@
1
1
  appraise "3.0" do
2
- gem "rails", "~> 3.0.12"
2
+ gem "rails", "~> 3.0.15"
3
3
  gem "paperclip", :path => "../"
4
4
  end
5
5
 
6
6
  appraise "3.1" do
7
- gem "rails", "~> 3.1.4"
7
+ gem "rails", "~> 3.1.6"
8
8
  gem "paperclip", :path => "../"
9
9
  end
10
10
 
11
11
  appraise "3.2" do
12
- gem "rails", "~> 3.2.3"
12
+ gem "rails", "~> 3.2.6"
13
13
  gem "paperclip", :path => "../"
14
14
  end
data/NEWS CHANGED
@@ -1,3 +1,46 @@
1
+ New in 3.1.0:
2
+
3
+ * Feature: Paperclip now support new migration syntax (sexy migration) that reads better:
4
+
5
+ class AddAttachmentToUsers < ActiveRecord::Migration
6
+ def self.up
7
+ create_table :users do |t|
8
+ t.attachment :avatar
9
+ end
10
+ end
11
+ end
12
+
13
+ Also, schema-definition level syntax has been added:
14
+
15
+ add_attachment :users, :avatar
16
+ remove_attachment :users, :avatar
17
+
18
+ * Feature: Migration now support Rails 3.2+ `change` method.
19
+ * API CHANGE: Old `t.has_attached_file` and `drop_attached_file` are now deprecated. You're advised
20
+ to update your migration file before the next MAJOR version.
21
+ * Bug fix: Tempfile now rewinded before generating fingerprint
22
+ * API CHANGE: Tempfiles are now unlinked after `after_flush_writes`
23
+
24
+ If you need to interact with the generated tempfiles, please define an `after_flush_writes` method
25
+ in your model. You'll be able to access files via `@queue_for_write` instance variable.
26
+
27
+ * Bug fix: `:s3_protocol` can now be defined as either String or Symbol
28
+ * Bug fix: Tempfiles are now rewinded before get passed into `after_flush_writes`
29
+ * Feature: Added expiring_url method to Fog Storage
30
+ * API CHANGE: Paperclip now tested against AWS::SDK 1.5.2 onward
31
+ * Bug fix: Improved the output of the content_type validator so the actual failure is displayed
32
+ * Feature: Animated formats now identified using ImageMagick.
33
+ * Feature: AttachmentAdapter now support fetching attachment with specific style.
34
+ * Feature: Paperclip default options can now be configured in Rails.configuration.
35
+ * Feature: add Geometry#resize_to to calculate dimensions of new source.
36
+ * Bug fix: Fixed a bug whereby a file type with multiple mime types but no official type would cause
37
+ the best_content_type to throw an error on trying nil.content_type.
38
+ * Bug fix: Fix problem when the gem cannot be installed on the system that has Asepsis installed.
39
+
40
+ New in 3.0.4:
41
+
42
+ * Feature: Adds support for S3 scheme-less URL generation.
43
+
1
44
  New in 3.0.3:
2
45
 
3
46
  * Bug fix: ThumbnailProcessor now correctly detects and preserve animated GIF.
data/README.md CHANGED
@@ -94,15 +94,13 @@ In your model:
94
94
 
95
95
  In your migrations:
96
96
 
97
- class AddAvatarColumnsToUser < ActiveRecord::Migration
97
+ class AddAvatarColumnsToUsers < ActiveRecord::Migration
98
98
  def self.up
99
- change_table :users do |t|
100
- t.has_attached_file :avatar
101
- end
99
+ add_attachment :users, :avatar
102
100
  end
103
101
 
104
102
  def self.down
105
- drop_attached_file :users, :avatar
103
+ remove_attachment :users, :avatar
106
104
  end
107
105
  end
108
106
 
@@ -180,6 +178,84 @@ Lastly, you can also define multiple validations on a single attachment using `v
180
178
  :content_type => { :content_type => "image/jpg" },
181
179
  :size => { :in => 0..10.kilobytes }
182
180
 
181
+ Defaults
182
+ --------
183
+ 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.
184
+
185
+ 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 well get merged into Paperclip::Attachment.default_options as your Rails app boots. An example:
186
+
187
+ ```ruby
188
+ module YourApp
189
+ class Application < Rails::Application
190
+ # Other code...
191
+
192
+ config.paperclip_defaults = {:storage => :fog, :fog_credentials => {:provider => "Local", :local_root => "#{Rails.root}/public"}, :fog_directory => "", :fog_host => "localhost"}
193
+ end
194
+ end
195
+ ```
196
+
197
+ 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.
198
+
199
+ An example Rails initializer would look something like this:
200
+
201
+ ```ruby
202
+ Paperclip::Attachment.default_options[:storage] = :fog
203
+ Paperclip::Attachment.default_options[:fog_credentials] = {:provider => "Local", :local_root => "#{Rails.root}/public"}
204
+ Paperclip::Attachment.default_options[:fog_directory] = ""
205
+ Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"}
206
+ ```
207
+
208
+ Migrations
209
+ ----------
210
+
211
+ Paperclip defines several migration methods which can be used to create necessary columns in your
212
+ model. There are two types of method:
213
+
214
+ ### Table Definition
215
+
216
+ class AddAttachmentToUsers < ActiveRecord::Migration
217
+ def self.up
218
+ create_table :users do |t|
219
+ t.attachment :avatar
220
+ end
221
+ end
222
+ end
223
+
224
+ If you're using Rails 3.2 or newer, this method works in `change` method as well:
225
+
226
+ class AddAttachmentToUsers < ActiveRecord::Migration
227
+ def change
228
+ create_table :users do |t|
229
+ t.attachment :avatar
230
+ end
231
+ end
232
+ end
233
+
234
+ ### Schema Definition
235
+
236
+ class AddAttachmentToUsers < ActiveRecord::Migration
237
+ def self.up
238
+ add_attachment :users, :avatar
239
+ end
240
+
241
+ def self.down
242
+ remove_attachment :users, :avatar
243
+ end
244
+ end
245
+
246
+ If you're using Rails 3.2 or newer, you only need `add_attachment` in your `change` method:
247
+
248
+ class AddAttachmentToUsers < ActiveRecord::Migration
249
+ def change
250
+ add_attachment :users, :avatar
251
+ end
252
+ end
253
+
254
+ ### Vintage syntax
255
+
256
+ Vintage syntax (such as `t.has_attached_file` and `drop_attaached_file`) are still supported in
257
+ Paperclip 3.x, but you're advised to update those migration files to use this new syntax.
258
+
183
259
  Storage
184
260
  -------
185
261
 
@@ -8,12 +8,30 @@ Feature: Rails integration
8
8
  And I update my new user view to include the file upload field
9
9
  And I update my user view to include the attachment
10
10
 
11
+ Scenario: Configure defaults for all attachments through Railtie
12
+ Given I add this snippet to config/application.rb:
13
+ """
14
+ config.paperclip_defaults = {:url => "/paperclip/custom/:attachment/:style/:filename"}
15
+ """
16
+ Given I add this snippet to the User model:
17
+ """
18
+ attr_accessible :name, :attachment
19
+ has_attached_file :attachment
20
+ """
21
+ And I start the rails application
22
+ When I go to the new user page
23
+ And I fill in "Name" with "something"
24
+ And I attach the file "test/fixtures/5k.png" to "Attachment"
25
+ And I press "Submit"
26
+ Then I should see "Name: something"
27
+ And I should see an image with a path of "/paperclip/custom/attachments/original/5k.png"
28
+ And the file at "/paperclip/custom/attachments/original/5k.png" should be the same as "test/fixtures/5k.png"
29
+
11
30
  Scenario: Filesystem integration test
12
31
  Given I add this snippet to the User model:
13
32
  """
14
33
  attr_accessible :name, :attachment
15
- has_attached_file :attachment, :url => "/system/:attachment/:style/:filename",
16
- :styles => { :square => "100x100#" }
34
+ has_attached_file :attachment, :url => "/system/:attachment/:style/:filename"
17
35
  """
18
36
  And I start the rails application
19
37
  When I go to the new user page
@@ -0,0 +1,94 @@
1
+ Feature: Migration
2
+
3
+ Background:
4
+ Given I generate a new rails application
5
+ And I write to "app/models/user.rb" with:
6
+ """
7
+ class User < ActiveRecord::Base; end
8
+ """
9
+
10
+ Scenario: Vintage syntax
11
+ When I write to "db/migrate/01_add_attachment_to_users.rb" with:
12
+ """
13
+ class AddAttachmentToUsers < ActiveRecord::Migration
14
+ def self.up
15
+ create_table :users do |t|
16
+ t.has_attached_file :avatar
17
+ end
18
+ end
19
+
20
+ def self.down
21
+ drop_attached_file :users, :avatar
22
+ end
23
+ end
24
+ """
25
+ And I run a migration
26
+ Then I should have attachment columns for "avatar"
27
+
28
+ When I rollback a migration
29
+ Then I should not have attachment columns for "avatar"
30
+
31
+ Scenario: New syntax with create_table
32
+ When I write to "db/migrate/01_add_attachment_to_users.rb" with:
33
+ """
34
+ class AddAttachmentToUsers < ActiveRecord::Migration
35
+ def self.up
36
+ create_table :users do |t|
37
+ t.attachment :avatar
38
+ end
39
+ end
40
+ end
41
+ """
42
+ And I run a migration
43
+ Then I should have attachment columns for "avatar"
44
+
45
+ Scenario: New syntax outside of create_table
46
+ When I write to "db/migrate/01_create_users.rb" with:
47
+ """
48
+ class CreateUsers < ActiveRecord::Migration
49
+ def self.up
50
+ create_table :users
51
+ end
52
+ end
53
+ """
54
+ And I write to "db/migrate/02_add_attachment_to_users.rb" with:
55
+ """
56
+ class AddAttachmentToUsers < ActiveRecord::Migration
57
+ def self.up
58
+ add_attachment :users, :avatar
59
+ end
60
+
61
+ def self.down
62
+ remove_attachment :users, :avatar
63
+ end
64
+ end
65
+ """
66
+ And I run a migration
67
+ Then I should have attachment columns for "avatar"
68
+
69
+ When I rollback a migration
70
+ Then I should not have attachment columns for "avatar"
71
+
72
+ Scenario: Rails 3.2 change method
73
+ Given I am using Rails newer than 3.1
74
+ When I write to "db/migrate/01_create_users.rb" with:
75
+ """
76
+ class CreateUsers < ActiveRecord::Migration
77
+ def self.up
78
+ create_table :users
79
+ end
80
+ end
81
+ """
82
+ When I write to "db/migrate/02_add_attachment_to_users.rb" with:
83
+ """
84
+ class AddAttachmentToUsers < ActiveRecord::Migration
85
+ def change
86
+ add_attachment :users, :avatar
87
+ end
88
+ end
89
+ """
90
+ And I run a migration
91
+ Then I should have attachment columns for "avatar"
92
+
93
+ When I rollback a migration
94
+ Then I should not have attachment columns for "avatar"
@@ -72,3 +72,31 @@ Then /^the attachment file "([^"]*)" should (not )?exist$/ do |filename, not_exi
72
72
  check_file_presence([attachment_path(filename)], !not_exist)
73
73
  end
74
74
  end
75
+
76
+ Then /^I should have attachment columns for "([^"]*)"$/ do |attachment_name|
77
+ in_current_dir do
78
+ columns = eval(`bundle exec #{runner_command} "puts User.columns.map{ |column| [column.name, column.type] }.inspect"`.strip)
79
+ expect_columns = [
80
+ ["#{attachment_name}_file_name", :string],
81
+ ["#{attachment_name}_content_type", :string],
82
+ ["#{attachment_name}_file_size", :integer],
83
+ ["#{attachment_name}_updated_at", :datetime]
84
+ ]
85
+
86
+ expect_columns.all?{ |column| columns.include? column }.should be_true
87
+ end
88
+ end
89
+
90
+ Then /^I should not have attachment columns for "([^"]*)"$/ do |attachment_name|
91
+ in_current_dir do
92
+ columns = eval(`bundle exec #{runner_command} "puts User.columns.map{ |column| [column.name, column.type] }.inspect"`.strip)
93
+ expect_columns = [
94
+ ["#{attachment_name}_file_name", :string],
95
+ ["#{attachment_name}_content_type", :string],
96
+ ["#{attachment_name}_file_size", :integer],
97
+ ["#{attachment_name}_updated_at", :datetime]
98
+ ]
99
+
100
+ expect_columns.none?{ |column| columns.include? column }.should be_true
101
+ end
102
+ end
@@ -29,7 +29,11 @@ Given /^I run a paperclip generator to add a paperclip "([^"]*)" to the "([^"]*)
29
29
  end
30
30
 
31
31
  Given /^I run a migration$/ do
32
- step %[I successfully run `bundle exec rake db:migrate`]
32
+ step %[I successfully run `bundle exec rake db:migrate --trace`]
33
+ end
34
+
35
+ When /^I rollback a migration$/ do
36
+ step %[I successfully run `bundle exec rake db:rollback STEPS=1 --trace`]
33
37
  end
34
38
 
35
39
  Given /^I update my new user view to include the file upload field$/ do
@@ -65,6 +69,14 @@ Given /^I add this snippet to the User model:$/ do |snippet|
65
69
  end
66
70
  end
67
71
 
72
+ Given /^I add this snippet to config\/application.rb:$/ do |snippet|
73
+ file_name = "config/application.rb"
74
+ in_current_dir do
75
+ content = File.read(file_name)
76
+ File.open(file_name, 'w') {|f| f << content.sub(/class Application < Rails::Application.*$/, "class Application < Rails::Application\n#{snippet}\n")}
77
+ end
78
+ end
79
+
68
80
  Given /^I start the rails application$/ do
69
81
  in_current_dir do
70
82
  require "./config/environment"
@@ -118,3 +130,9 @@ end
118
130
  When /^I comment out the gem "([^"]*)" from the Gemfile$/ do |gemname|
119
131
  comment_out_gem_in_gemfile gemname
120
132
  end
133
+
134
+ Given /^I am using Rails newer than ([\d\.]+)$/ do |version|
135
+ if framework_version < version
136
+ pending "Not supported in Rails < #{version}"
137
+ end
138
+ end
@@ -181,7 +181,7 @@ Then /^the "([^"]*)" checkbox(?: within (.*))? should not be checked$/ do |label
181
181
  end
182
182
  end
183
183
  end
184
-
184
+
185
185
  Then /^(?:|I )should be on (.+)$/ do |page_name|
186
186
  current_path = URI.parse(current_url).path
187
187
  if current_path.respond_to? :should
@@ -195,8 +195,8 @@ Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
195
195
  query = URI.parse(current_url).query
196
196
  actual_params = query ? CGI.parse(query) : {}
197
197
  expected_params = {}
198
- expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
199
-
198
+ expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
199
+
200
200
  if actual_params.respond_to? :should
201
201
  actual_params.should == expected_params
202
202
  else
@@ -5,7 +5,7 @@ source "http://rubygems.org"
5
5
  gem "jruby-openssl", :platform=>:jruby
6
6
  gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
7
7
  gem "sqlite3", :platform=>:ruby
8
- gem "rails", "~> 3.0.12"
8
+ gem "rails", "~> 3.0.15"
9
9
  gem "paperclip", :path=>"../"
10
10
 
11
11
  gemspec :path=>"../"
@@ -5,7 +5,7 @@ source "http://rubygems.org"
5
5
  gem "jruby-openssl", :platform=>:jruby
6
6
  gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
7
7
  gem "sqlite3", :platform=>:ruby
8
- gem "rails", "~> 3.1.4"
8
+ gem "rails", "~> 3.1.6"
9
9
  gem "paperclip", :path=>"../"
10
10
 
11
11
  gemspec :path=>"../"
@@ -5,7 +5,7 @@ source "http://rubygems.org"
5
5
  gem "jruby-openssl", :platform=>:jruby
6
6
  gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
7
7
  gem "sqlite3", :platform=>:ruby
8
- gem "rails", "~> 3.2.3"
8
+ gem "rails", "~> 3.2.6"
9
9
  gem "paperclip", :path=>"../"
10
10
 
11
11
  gemspec :path=>"../"
@@ -1,19 +1,15 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration
2
2
  def self.up
3
+ change_table :<%= table_name %> do |t|
3
4
  <% attachment_names.each do |attachment| -%>
4
- add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_name, :string
5
- add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_content_type, :string
6
- add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_size, :integer
7
- add_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at, :datetime
5
+ t.has_attached_file :<%= attachment %>
8
6
  <% end -%>
7
+ end
9
8
  end
10
9
 
11
10
  def self.down
12
11
  <% attachment_names.each do |attachment| -%>
13
- remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_name
14
- remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_content_type
15
- remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_file_size
16
- remove_column :<%= name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at
12
+ drop_attached_file :<%= table_name %>, :<%= attachment %>
17
13
  <% end -%>
18
14
  end
19
15
  end
@@ -34,6 +34,7 @@ require 'paperclip/processor'
34
34
  require 'paperclip/tempfile'
35
35
  require 'paperclip/thumbnail'
36
36
  require 'paperclip/interpolations'
37
+ require 'paperclip/tempfile_factory'
37
38
  require 'paperclip/style'
38
39
  require 'paperclip/attachment'
39
40
  require 'paperclip/attachment_options'
@@ -214,6 +215,7 @@ end
214
215
 
215
216
  # This stuff needs to be run after Paperclip is defined.
216
217
  require 'paperclip/io_adapters/registry'
218
+ require 'paperclip/io_adapters/abstract_adapter'
217
219
  require 'paperclip/io_adapters/identity_adapter'
218
220
  require 'paperclip/io_adapters/file_adapter'
219
221
  require 'paperclip/io_adapters/stringio_adapter'