cloudfuji_paperclip 2.4.6
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.
- data/.gitignore +22 -0
- data/.travis.yml +13 -0
- data/Appraisals +14 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +137 -0
- data/LICENSE +26 -0
- data/README.md +444 -0
- data/Rakefile +41 -0
- data/cucumber/paperclip_steps.rb +6 -0
- data/features/basic_integration.feature +46 -0
- data/features/rake_tasks.feature +63 -0
- data/features/step_definitions/attachment_steps.rb +65 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +182 -0
- data/features/step_definitions/s3_steps.rb +14 -0
- data/features/step_definitions/web_steps.rb +209 -0
- data/features/support/env.rb +8 -0
- data/features/support/fakeweb.rb +3 -0
- data/features/support/fixtures/.boot_config.rb.swo +0 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +46 -0
- data/features/support/selectors.rb +19 -0
- data/gemfiles/rails2.gemfile +9 -0
- data/gemfiles/rails3.gemfile +9 -0
- data/gemfiles/rails3_1.gemfile +9 -0
- data/generators/paperclip/USAGE +5 -0
- data/generators/paperclip/paperclip_generator.rb +27 -0
- data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
- data/init.rb +4 -0
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +33 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
- data/lib/paperclip/attachment.rb +468 -0
- data/lib/paperclip/callback_compatibility.rb +61 -0
- data/lib/paperclip/geometry.rb +120 -0
- data/lib/paperclip/interpolations.rb +174 -0
- data/lib/paperclip/iostream.rb +45 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +81 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
- data/lib/paperclip/matchers.rb +64 -0
- data/lib/paperclip/missing_attachment_styles.rb +87 -0
- data/lib/paperclip/processor.rb +58 -0
- data/lib/paperclip/railtie.rb +31 -0
- data/lib/paperclip/schema.rb +39 -0
- data/lib/paperclip/storage/filesystem.rb +81 -0
- data/lib/paperclip/storage/fog.rb +174 -0
- data/lib/paperclip/storage/s3.rb +333 -0
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/style.rb +103 -0
- data/lib/paperclip/thumbnail.rb +105 -0
- data/lib/paperclip/upfile.rb +62 -0
- data/lib/paperclip/url_generator.rb +64 -0
- data/lib/paperclip/version.rb +3 -0
- data/lib/paperclip.rb +487 -0
- data/lib/tasks/paperclip.rake +101 -0
- data/paperclip.gemspec +41 -0
- data/rails/init.rb +2 -0
- data/shoulda_macros/paperclip.rb +124 -0
- data/test/.gitignore +1 -0
- data/test/attachment_test.rb +1116 -0
- data/test/database.yml +4 -0
- data/test/fixtures/12k.png +0 -0
- data/test/fixtures/50x50.png +0 -0
- data/test/fixtures/5k.png +0 -0
- data/test/fixtures/animated.gif +0 -0
- data/test/fixtures/bad.png +1 -0
- data/test/fixtures/fog.yml +8 -0
- data/test/fixtures/question?mark.png +0 -0
- data/test/fixtures/s3.yml +8 -0
- data/test/fixtures/spaced file.png +0 -0
- data/test/fixtures/text.txt +1 -0
- data/test/fixtures/twopage.pdf +0 -0
- data/test/fixtures/uppercase.PNG +0 -0
- data/test/geometry_test.rb +206 -0
- data/test/helper.rb +177 -0
- data/test/integration_test.rb +654 -0
- data/test/interpolations_test.rb +216 -0
- data/test/iostream_test.rb +71 -0
- data/test/matchers/have_attached_file_matcher_test.rb +24 -0
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +87 -0
- data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
- data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
- data/test/paperclip_missing_attachment_styles_test.rb +80 -0
- data/test/paperclip_test.rb +390 -0
- data/test/processor_test.rb +10 -0
- data/test/schema_test.rb +98 -0
- data/test/storage/filesystem_test.rb +56 -0
- data/test/storage/fog_test.rb +219 -0
- data/test/storage/s3_live_test.rb +138 -0
- data/test/storage/s3_test.rb +943 -0
- data/test/style_test.rb +209 -0
- data/test/support/mock_attachment.rb +22 -0
- data/test/support/mock_interpolator.rb +24 -0
- data/test/support/mock_model.rb +2 -0
- data/test/support/mock_url_generator_builder.rb +27 -0
- data/test/thumbnail_test.rb +383 -0
- data/test/upfile_test.rb +53 -0
- data/test/url_generator_test.rb +187 -0
- metadata +404 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
require './test/helper'
|
|
2
|
+
require 'fog'
|
|
3
|
+
|
|
4
|
+
Fog.mock!
|
|
5
|
+
|
|
6
|
+
class FogTest < Test::Unit::TestCase
|
|
7
|
+
context "" do
|
|
8
|
+
|
|
9
|
+
context "with credentials provided in a path string" do
|
|
10
|
+
setup do
|
|
11
|
+
rebuild_model :styles => { :medium => "300x300>", :thumb => "100x100>" },
|
|
12
|
+
:storage => :fog,
|
|
13
|
+
:url => '/:attachment/:filename',
|
|
14
|
+
:fog_directory => "paperclip",
|
|
15
|
+
:fog_credentials => fixture_file('fog.yml')
|
|
16
|
+
@dummy = Dummy.new
|
|
17
|
+
@dummy.avatar = File.new(fixture_file('5k.png'), 'rb')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "have the proper information loading credentials from a file" do
|
|
21
|
+
assert_equal @dummy.avatar.fog_credentials[:provider], 'AWS'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "with credentials provided in a File object" do
|
|
26
|
+
setup do
|
|
27
|
+
rebuild_model :styles => { :medium => "300x300>", :thumb => "100x100>" },
|
|
28
|
+
:storage => :fog,
|
|
29
|
+
:url => '/:attachment/:filename',
|
|
30
|
+
:fog_directory => "paperclip",
|
|
31
|
+
:fog_credentials => File.open(fixture_file('fog.yml'))
|
|
32
|
+
@dummy = Dummy.new
|
|
33
|
+
@dummy.avatar = File.new(fixture_file('5k.png'), 'rb')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
should "have the proper information loading credentials from a file" do
|
|
37
|
+
assert_equal @dummy.avatar.fog_credentials[:provider], 'AWS'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "with default values for path and url" do
|
|
42
|
+
setup do
|
|
43
|
+
rebuild_model :styles => { :medium => "300x300>", :thumb => "100x100>" },
|
|
44
|
+
:storage => :fog,
|
|
45
|
+
:url => '/:attachment/:filename',
|
|
46
|
+
:fog_directory => "paperclip",
|
|
47
|
+
:fog_credentials => {
|
|
48
|
+
:provider => 'AWS',
|
|
49
|
+
:aws_access_key_id => 'AWS_ID',
|
|
50
|
+
:aws_secret_access_key => 'AWS_SECRET'
|
|
51
|
+
}
|
|
52
|
+
@dummy = Dummy.new
|
|
53
|
+
@dummy.avatar = File.new(fixture_file('5k.png'), 'rb')
|
|
54
|
+
end
|
|
55
|
+
should "be able to interpolate the path without blowing up" do
|
|
56
|
+
assert_equal File.expand_path(File.join(File.dirname(__FILE__), "../../public/avatars/5k.png")),
|
|
57
|
+
@dummy.avatar.path
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
should "clean up file objects" do
|
|
61
|
+
File.stubs(:exist?).returns(true)
|
|
62
|
+
Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
|
|
63
|
+
Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
|
|
64
|
+
|
|
65
|
+
@dummy.save!
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
setup do
|
|
70
|
+
@fog_directory = 'papercliptests'
|
|
71
|
+
|
|
72
|
+
@credentials = {
|
|
73
|
+
:provider => 'AWS',
|
|
74
|
+
:aws_access_key_id => 'ID',
|
|
75
|
+
:aws_secret_access_key => 'SECRET'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@connection = Fog::Storage.new(@credentials)
|
|
79
|
+
@connection.directories.create(
|
|
80
|
+
:key => @fog_directory
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@options = {
|
|
84
|
+
:fog_directory => @fog_directory,
|
|
85
|
+
:fog_credentials => @credentials,
|
|
86
|
+
:fog_host => nil,
|
|
87
|
+
:fog_file => {:cache_control => 1234},
|
|
88
|
+
:path => ":attachment/:basename.:extension",
|
|
89
|
+
:storage => :fog
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
rebuild_model(@options)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
should "be extended by the Fog module" do
|
|
96
|
+
assert Dummy.new.avatar.is_a?(Paperclip::Storage::Fog)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "when assigned" do
|
|
100
|
+
setup do
|
|
101
|
+
@file = File.new(fixture_file('5k.png'), 'rb')
|
|
102
|
+
@dummy = Dummy.new
|
|
103
|
+
@dummy.avatar = @file
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
teardown do
|
|
107
|
+
@file.close
|
|
108
|
+
directory = @connection.directories.new(:key => @fog_directory)
|
|
109
|
+
directory.files.each {|file| file.destroy}
|
|
110
|
+
directory.destroy
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "without a bucket" do
|
|
114
|
+
setup do
|
|
115
|
+
@connection.directories.get(@fog_directory).destroy
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
should "create the bucket" do
|
|
119
|
+
assert @dummy.save
|
|
120
|
+
assert @connection.directories.get(@fog_directory)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "with a bucket" do
|
|
125
|
+
should "succeed" do
|
|
126
|
+
assert @dummy.save
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "without a fog_host" do
|
|
131
|
+
setup do
|
|
132
|
+
rebuild_model(@options.merge(:fog_host => nil))
|
|
133
|
+
@dummy = Dummy.new
|
|
134
|
+
@dummy.avatar = StringIO.new('.')
|
|
135
|
+
@dummy.save
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
should "provide a public url" do
|
|
139
|
+
assert !@dummy.avatar.url.nil?
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context "with a fog_host" do
|
|
144
|
+
setup do
|
|
145
|
+
rebuild_model(@options.merge(:fog_host => 'http://example.com'))
|
|
146
|
+
@dummy = Dummy.new
|
|
147
|
+
@dummy.avatar = StringIO.new('.')
|
|
148
|
+
@dummy.save
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
should "provide a public url" do
|
|
152
|
+
assert @dummy.avatar.url =~ /^http:\/\/example\.com\/avatars\/stringio\.txt\?\d*$/
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context "with a fog_host that includes a wildcard placeholder" do
|
|
157
|
+
setup do
|
|
158
|
+
rebuild_model(
|
|
159
|
+
:fog_directory => @fog_directory,
|
|
160
|
+
:fog_credentials => @credentials,
|
|
161
|
+
:fog_host => 'http://img%d.example.com',
|
|
162
|
+
:path => ":attachment/:basename.:extension",
|
|
163
|
+
:storage => :fog
|
|
164
|
+
)
|
|
165
|
+
@dummy = Dummy.new
|
|
166
|
+
@dummy.avatar = StringIO.new('.')
|
|
167
|
+
@dummy.save
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
should "provide a public url" do
|
|
171
|
+
assert @dummy.avatar.url =~ /^http:\/\/img[0123]\.example\.com\/avatars\/stringio\.txt\?\d*$/
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "with fog_public set to false" do
|
|
176
|
+
setup do
|
|
177
|
+
rebuild_model(@options.merge(:fog_public => false))
|
|
178
|
+
@dummy = Dummy.new
|
|
179
|
+
@dummy.avatar = StringIO.new('.')
|
|
180
|
+
@dummy.save
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
should 'set the @fog_public instance variable to false' do
|
|
184
|
+
assert_equal false, @dummy.avatar.instance_variable_get('@options')[:fog_public]
|
|
185
|
+
assert_equal false, @dummy.avatar.fog_public
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
context "with a valid bucket name for a subdomain" do
|
|
190
|
+
should "provide an url in subdomain style" do
|
|
191
|
+
assert_match /^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png\?\d*$/, @dummy.avatar.url
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context "with an invalid bucket name for a subdomain" do
|
|
196
|
+
setup do
|
|
197
|
+
rebuild_model(@options.merge(:fog_directory => "this_is_invalid"))
|
|
198
|
+
@dummy = Dummy.new
|
|
199
|
+
@dummy.avatar = @file
|
|
200
|
+
@dummy.save
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
should "not match the bucket-subdomain restrictions" do
|
|
204
|
+
invalid_subdomains = %w(this_is_invalid in iamareallylongbucketnameiamareallylongbucketnameiamareallylongbu invalid- inval..id inval-.id inval.-id -invalid 192.168.10.2)
|
|
205
|
+
invalid_subdomains.each do |name|
|
|
206
|
+
assert_no_match Paperclip::Storage::Fog::AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX, name
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
should "provide an url in folder style" do
|
|
211
|
+
assert_match /^https:\/\/s3.amazonaws.com\/this_is_invalid\/avatars\/5k.png\?\d*$/, @dummy.avatar.url
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
end
|
|
219
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require './test/helper'
|
|
2
|
+
require 'aws'
|
|
3
|
+
|
|
4
|
+
unless ENV["S3_BUCKET"].blank?
|
|
5
|
+
class S3LiveTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
context "Generating an expiring url on a nonexistant attachment" do
|
|
8
|
+
setup do
|
|
9
|
+
rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
|
|
10
|
+
:storage => :s3,
|
|
11
|
+
:bucket => ENV["S3_BUCKET"],
|
|
12
|
+
:path => ":class/:attachment/:id/:style.:extension",
|
|
13
|
+
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "fixtures", "s3.yml"))
|
|
14
|
+
|
|
15
|
+
@dummy = Dummy.new
|
|
16
|
+
end
|
|
17
|
+
should "return nil" do
|
|
18
|
+
assert_nil @dummy.avatar.expiring_url
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "Using S3 for real, an attachment with S3 storage" do
|
|
23
|
+
setup do
|
|
24
|
+
rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
|
|
25
|
+
:storage => :s3,
|
|
26
|
+
:bucket => ENV["S3_BUCKET"],
|
|
27
|
+
:path => ":class/:attachment/:id/:style.:extension",
|
|
28
|
+
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "fixtures", "s3.yml"))
|
|
29
|
+
|
|
30
|
+
Dummy.delete_all
|
|
31
|
+
@dummy = Dummy.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "be extended by the S3 module" do
|
|
35
|
+
assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "when assigned" do
|
|
39
|
+
setup do
|
|
40
|
+
@file = File.new(fixture_file('5k.png'), 'rb')
|
|
41
|
+
@dummy.avatar = @file
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
teardown do
|
|
45
|
+
@file.close
|
|
46
|
+
@dummy.destroy
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
should "still return a Tempfile when sent #to_file" do
|
|
50
|
+
assert_equal Paperclip::Tempfile, @dummy.avatar.to_file.class
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "and saved" do
|
|
54
|
+
setup do
|
|
55
|
+
@dummy.save
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
should "be on S3" do
|
|
59
|
+
assert true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
should "generate a tempfile with the right name" do
|
|
63
|
+
file = @dummy.avatar.to_file
|
|
64
|
+
assert_match /^original.*\.png$/, File.basename(file.path)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "An attachment that uses S3 for storage and has spaces in file name" do
|
|
71
|
+
setup do
|
|
72
|
+
rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
|
|
73
|
+
:storage => :s3,
|
|
74
|
+
:bucket => ENV["S3_BUCKET"],
|
|
75
|
+
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "fixtures", "s3.yml"))
|
|
76
|
+
|
|
77
|
+
Dummy.delete_all
|
|
78
|
+
@dummy = Dummy.new
|
|
79
|
+
@dummy.avatar = File.new(fixture_file('spaced file.png'), 'rb')
|
|
80
|
+
@dummy.save
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
should "return an unescaped version for path" do
|
|
84
|
+
assert_match /.+\/spaced file\.png/, @dummy.avatar.path
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
should "return an escaped version for url" do
|
|
88
|
+
assert_match /.+\/spaced%20file\.png/, @dummy.avatar.url
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
should "be accessible" do
|
|
92
|
+
assert_success_response @dummy.avatar.url
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
should "be destoryable" do
|
|
96
|
+
url = @dummy.avatar.url
|
|
97
|
+
@dummy.destroy
|
|
98
|
+
assert_not_found_response url
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "An attachment that uses S3 for storage and has a question mark in file name" do
|
|
103
|
+
setup do
|
|
104
|
+
rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
|
|
105
|
+
:storage => :s3,
|
|
106
|
+
:bucket => ENV["S3_BUCKET"],
|
|
107
|
+
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "fixtures", "s3.yml"))
|
|
108
|
+
|
|
109
|
+
Dummy.delete_all
|
|
110
|
+
@dummy = Dummy.new
|
|
111
|
+
@dummy.avatar = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', 'question?mark.png'), 'rb')
|
|
112
|
+
@dummy.save
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
should "return an unescaped version for path" do
|
|
116
|
+
assert_match /.+\/question\?mark\.png/, @dummy.avatar.path
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
should "return an escaped version for url" do
|
|
120
|
+
assert_match /.+\/question%3Fmark\.png/, @dummy.avatar.url
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
should "be accessible" do
|
|
124
|
+
assert_success_response @dummy.avatar.url
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
should "be accessible with an expiring url" do
|
|
128
|
+
assert_success_response @dummy.avatar.expiring_url
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
should "be destroyable" do
|
|
132
|
+
url = @dummy.avatar.url
|
|
133
|
+
@dummy.destroy
|
|
134
|
+
assert_not_found_response url
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|