paperclip-azure 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +1 -30
- data/{README.txt → README.md} +1 -2
- data/lib/paperclip/azure.rb +1 -1
- metadata +4 -33
- data/spec/database.yml +0 -3
- data/spec/paperclip/storage/azure/environment_spec.rb +0 -26
- data/spec/paperclip/storage/azure_spec.rb +0 -435
- data/spec/spec_helper.rb +0 -56
- data/spec/support/fake_model.rb +0 -25
- data/spec/support/fake_rails.rb +0 -12
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/azure.yml +0 -8
- data/spec/support/fixtures/bad.png +0 -1
- data/spec/support/fixtures/empty.html +0 -1
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +0 -8
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +0 -1
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/mock_attachment.rb +0 -24
- data/spec/support/mock_interpolator.rb +0 -24
- data/spec/support/mock_url_generator_builder.rb +0 -27
- data/spec/support/model_reconstruction.rb +0 -68
- data/spec/support/test_data.rb +0 -13
- data/spec/support/version_helper.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91658bf1e2cf4f471f3b5a93a155b616efb4390f
|
4
|
+
data.tar.gz: 2fa21b6a99bc0e528879a513f91fab385261982e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daf2b746df97d6c254887830b2e99c88e7a4a15c5c4b9160a2f975945301ba803959fa0608fe7d0c352187639fc613252fe8ca3946acefdb2eeaab682872e37e
|
7
|
+
data.tar.gz: 2f58905f8e83a9f358038544efba09b579e8a9ccdb0893901123429ced6de3567bc3d0b085b70f13f631e0ee389ebb3b13248cd1b63391a3fe5625e8e2c104ea
|
data/Manifest.txt
CHANGED
@@ -1,38 +1,9 @@
|
|
1
1
|
.autotest
|
2
2
|
History.txt
|
3
3
|
Manifest.txt
|
4
|
-
README.
|
4
|
+
README.md
|
5
5
|
Rakefile
|
6
6
|
lib/paperclip/storage/azure/environment.rb
|
7
7
|
lib/paperclip/storage/azure.rb
|
8
8
|
lib/paperclip/azure.rb
|
9
9
|
lib/paperclip-azure.rb
|
10
|
-
spec/paperclip/storage/azure/environment_spec.rb
|
11
|
-
spec/paperclip/storage/azure_spec.rb
|
12
|
-
spec/support/fixtures/12k.png
|
13
|
-
spec/support/fixtures/50x50.png
|
14
|
-
spec/support/fixtures/5k.png
|
15
|
-
spec/support/fixtures/animated
|
16
|
-
spec/support/fixtures/animated.gif
|
17
|
-
spec/support/fixtures/animated.unknown
|
18
|
-
spec/support/fixtures/azure.yml
|
19
|
-
spec/support/fixtures/bad.png
|
20
|
-
spec/support/fixtures/empty.html
|
21
|
-
spec/support/fixtures/empty.xlsx
|
22
|
-
spec/support/fixtures/fog.yml
|
23
|
-
spec/support/fixtures/rotated.jpg
|
24
|
-
spec/support/fixtures/spaced file.jpg
|
25
|
-
spec/support/fixtures/spaced file.png
|
26
|
-
spec/support/fixtures/text.txt
|
27
|
-
spec/support/fixtures/twopage.pdf
|
28
|
-
spec/support/fixtures/uppercase.PNG
|
29
|
-
spec/support/fake_model.rb
|
30
|
-
spec/support/fake_rails.rb
|
31
|
-
spec/support/mock_attachment.rb
|
32
|
-
spec/support/mock_interpolator.rb
|
33
|
-
spec/support/mock_url_generator_builder.rb
|
34
|
-
spec/support/model_reconstruction.rb
|
35
|
-
spec/support/test_data.rb
|
36
|
-
spec/support/version_helper.rb
|
37
|
-
spec/database.yml
|
38
|
-
spec/spec_helper.rb
|
data/{README.txt → README.md}
RENAMED
@@ -18,8 +18,6 @@ Paperclip-Azure is a [Paperclip](https://github.com/thoughtbot/paperclip) storag
|
|
18
18
|
The Azure storage engine has been developed to work as similarly to S3 storage configuration as is possible. This gem can be configured in a Paperclip initializer or environment file as follows:
|
19
19
|
|
20
20
|
Paperclip::Attachment.default_options[:storage] = :azure
|
21
|
-
Paperclip::Attachment.default_options[:url] = ':azure_path_url'
|
22
|
-
Paperclip::Attachment.default_options[:path] = ':class/:attachment/:id/:style/:filename'
|
23
21
|
Paperclip::Attachment.default_options[:azure_credentials] = {
|
24
22
|
storage_account_name: ENV['AZURE_STORAGE_ACCOUNT'],
|
25
23
|
storage_access_key: ENV['AZURE_STORAGE_ACCESS_KEY'],
|
@@ -55,6 +53,7 @@ This is not required, however, and the file may simply look like this:
|
|
55
53
|
|
56
54
|
In which case, those access keys will be used in all environments. You can also put your container name in this file, instead of adding it to the code directly. This is useful when you want the same account but a different container for development versus production.
|
57
55
|
|
56
|
+
|
58
57
|
=== Private Blob Access
|
59
58
|
|
60
59
|
In the even that are using a Blob that has been configured for Private access, you will need to use the Shared Access Signature functionality of Azure. This functionality has been baked in to the `Attachment#expiring_url` method. Simply specify a time and a style and you will get a proper URL as follows:
|
data/lib/paperclip/azure.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paperclip-azure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hireross.com
|
@@ -215,46 +215,17 @@ extensions: []
|
|
215
215
|
extra_rdoc_files:
|
216
216
|
- History.txt
|
217
217
|
- Manifest.txt
|
218
|
-
- README.
|
218
|
+
- README.md
|
219
219
|
files:
|
220
220
|
- ".autotest"
|
221
221
|
- History.txt
|
222
222
|
- Manifest.txt
|
223
|
-
- README.
|
223
|
+
- README.md
|
224
224
|
- Rakefile
|
225
225
|
- lib/paperclip-azure.rb
|
226
226
|
- lib/paperclip/azure.rb
|
227
227
|
- lib/paperclip/storage/azure.rb
|
228
228
|
- lib/paperclip/storage/azure/environment.rb
|
229
|
-
- spec/database.yml
|
230
|
-
- spec/paperclip/storage/azure/environment_spec.rb
|
231
|
-
- spec/paperclip/storage/azure_spec.rb
|
232
|
-
- spec/spec_helper.rb
|
233
|
-
- spec/support/fake_model.rb
|
234
|
-
- spec/support/fake_rails.rb
|
235
|
-
- spec/support/fixtures/12k.png
|
236
|
-
- spec/support/fixtures/50x50.png
|
237
|
-
- spec/support/fixtures/5k.png
|
238
|
-
- spec/support/fixtures/animated
|
239
|
-
- spec/support/fixtures/animated.gif
|
240
|
-
- spec/support/fixtures/animated.unknown
|
241
|
-
- spec/support/fixtures/azure.yml
|
242
|
-
- spec/support/fixtures/bad.png
|
243
|
-
- spec/support/fixtures/empty.html
|
244
|
-
- spec/support/fixtures/empty.xlsx
|
245
|
-
- spec/support/fixtures/fog.yml
|
246
|
-
- spec/support/fixtures/rotated.jpg
|
247
|
-
- spec/support/fixtures/spaced file.jpg
|
248
|
-
- spec/support/fixtures/spaced file.png
|
249
|
-
- spec/support/fixtures/text.txt
|
250
|
-
- spec/support/fixtures/twopage.pdf
|
251
|
-
- spec/support/fixtures/uppercase.PNG
|
252
|
-
- spec/support/mock_attachment.rb
|
253
|
-
- spec/support/mock_interpolator.rb
|
254
|
-
- spec/support/mock_url_generator_builder.rb
|
255
|
-
- spec/support/model_reconstruction.rb
|
256
|
-
- spec/support/test_data.rb
|
257
|
-
- spec/support/version_helper.rb
|
258
229
|
homepage: https://github.com/supportify/paperclip-azure
|
259
230
|
licenses:
|
260
231
|
- MIT
|
@@ -262,7 +233,7 @@ metadata: {}
|
|
262
233
|
post_install_message:
|
263
234
|
rdoc_options:
|
264
235
|
- "--main"
|
265
|
-
- README.
|
236
|
+
- README.md
|
266
237
|
require_paths:
|
267
238
|
- lib
|
268
239
|
required_ruby_version: !ruby/object:Gem::Requirement
|
data/spec/database.yml
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'paperclip/storage/azure/environment'
|
3
|
-
|
4
|
-
describe 'Paperclip::Storage::Azure::Environment' do
|
5
|
-
subject { Paperclip::Storage::Azure::Environment }
|
6
|
-
|
7
|
-
describe '#url_for' do
|
8
|
-
let(:account_name) { 'foo' }
|
9
|
-
|
10
|
-
describe 'when the region is not supplied' do
|
11
|
-
it { expect(subject.url_for(account_name)).to eq("#{account_name}.blob.core.windows.net")}
|
12
|
-
end
|
13
|
-
|
14
|
-
describe 'when the region is China' do
|
15
|
-
it { expect(subject.url_for(account_name, :cn)).to eq("#{account_name}.blob.core.chinacloudapi.cn")}
|
16
|
-
end
|
17
|
-
|
18
|
-
describe 'when the region is Germany' do
|
19
|
-
it { expect(subject.url_for(account_name, :de)).to eq("#{account_name}.blob.core.cloudapi.de")}
|
20
|
-
end
|
21
|
-
|
22
|
-
describe 'when the region is the US Govt' do
|
23
|
-
it { expect(subject.url_for(account_name, :usgovt)).to eq("#{account_name}.blob.core.usgovcloudapi.net")}
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,435 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require "base64"
|
3
|
-
|
4
|
-
describe Paperclip::Storage::Azure do
|
5
|
-
let(:storage_access_key) { 'kiaY4+GkLMVxnfOK2X+eCJOE06J8QtHC6XNuXVwt8Pp4kMezYaa7cNjtYnZr4/b732RKdz5pZwl8RN9yb8gBCg==' }
|
6
|
-
|
7
|
-
describe "#parse_credentials" do
|
8
|
-
let(:credentials) {{
|
9
|
-
'production' => {key: '12345'},
|
10
|
-
development: {key: "54321"}
|
11
|
-
}}
|
12
|
-
|
13
|
-
before do
|
14
|
-
@proxy_settings = {host: "127.0.0.1", port: 8888, user: "foo", password: "bar"}
|
15
|
-
rebuild_model storage: :azure,
|
16
|
-
container: "testing",
|
17
|
-
azure_credentials: {not: :important}
|
18
|
-
@dummy = Dummy.new
|
19
|
-
@avatar = @dummy.avatar
|
20
|
-
end
|
21
|
-
|
22
|
-
it "gets the correct credentials when RAILS_ENV is production" do
|
23
|
-
rails_env("production") do
|
24
|
-
expect(@avatar.parse_credentials(credentials)).to eq({key: "12345"})
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
it "gets the correct credentials when RAILS_ENV is development" do
|
29
|
-
rails_env("development") do
|
30
|
-
expect(@avatar.parse_credentials(credentials)).to eq({key: "54321"})
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it "returns the argument if the key does not exist" do
|
35
|
-
rails_env("not really an env") do
|
36
|
-
expect(@avatar.parse_credentials(test: "12345")).to eq({test: "12345"})
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
describe '#container_name' do
|
43
|
-
describe ":container option via :azure_credentials" do
|
44
|
-
before do
|
45
|
-
rebuild_model storage: :azure,
|
46
|
-
azure_credentials: {container: 'testing'}
|
47
|
-
@dummy = Dummy.new
|
48
|
-
end
|
49
|
-
|
50
|
-
it "populates #container_name" do
|
51
|
-
expect(@dummy.avatar.container_name).to eq('testing')
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
describe ":container option" do
|
56
|
-
before do
|
57
|
-
rebuild_model storage: :azure,
|
58
|
-
container: "testing",
|
59
|
-
azure_credentials: {}
|
60
|
-
@dummy = Dummy.new
|
61
|
-
end
|
62
|
-
|
63
|
-
it "populates #container_name" do
|
64
|
-
expect(@dummy.avatar.container_name).to eq('testing')
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "missing :container option" do
|
69
|
-
before do
|
70
|
-
rebuild_model storage: :azure,
|
71
|
-
azure_credentials: {not: :important}
|
72
|
-
|
73
|
-
@dummy = Dummy.new
|
74
|
-
@dummy.avatar = stringy_file
|
75
|
-
end
|
76
|
-
|
77
|
-
it "raises an argument error" do
|
78
|
-
expect{ @dummy.avatar.container_name }.to raise_error(ArgumentError, /missing required :container option/)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
describe "" do
|
84
|
-
before do
|
85
|
-
rebuild_model storage: :azure,
|
86
|
-
azure_credentials: {
|
87
|
-
storage_account_name: 'storage',
|
88
|
-
storage_access_key: storage_access_key
|
89
|
-
},
|
90
|
-
container: "container",
|
91
|
-
path: ":attachment/:basename:dotextension",
|
92
|
-
url: ":azure_path_url"
|
93
|
-
|
94
|
-
@dummy = Dummy.new
|
95
|
-
@dummy.avatar = stringy_file
|
96
|
-
|
97
|
-
allow(@dummy).to receive(:new_record?).and_return(false)
|
98
|
-
end
|
99
|
-
|
100
|
-
it "returns urls based on Azure paths" do
|
101
|
-
expect(@dummy.avatar.url).to match(%r{^https://storage.blob.core.windows.net/container/avatars/data[^\.]})
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
describe "An attachment that uses Azure for storage and has styles that return different file types" do
|
106
|
-
before do
|
107
|
-
rebuild_model storage: :azure,
|
108
|
-
styles: { large: ['500x500#', :jpg] },
|
109
|
-
container: "container",
|
110
|
-
path: ":attachment/:basename:dotextension",
|
111
|
-
azure_credentials: {
|
112
|
-
'access_key_id' => "12345",
|
113
|
-
'secret_access_key' => "54321"
|
114
|
-
}
|
115
|
-
|
116
|
-
File.open(fixture_file('5k.png'), 'rb') do |file|
|
117
|
-
@dummy = Dummy.new
|
118
|
-
@dummy.avatar = file
|
119
|
-
|
120
|
-
allow(@dummy).to receive(:new_record?).and_return(false)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
it "returns a url containing the correct original file mime type" do
|
125
|
-
expect(@dummy.avatar.url).to match(/.+\/5k.png/)
|
126
|
-
end
|
127
|
-
|
128
|
-
it "returns a url containing the correct processed file mime type" do
|
129
|
-
expect(@dummy.avatar.url(:large)).to match(/.+\/5k.jpg/)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
describe "An attachment that uses Azure for storage and has spaces in file name" do
|
134
|
-
before do
|
135
|
-
rebuild_model storage: :azure,
|
136
|
-
styles: { large: ["500x500#", :jpg] },
|
137
|
-
container: "container",
|
138
|
-
azure_credentials: {
|
139
|
-
"storage_access_key" => "54321"
|
140
|
-
}
|
141
|
-
|
142
|
-
File.open(fixture_file("spaced file.png"), "rb") do |file|
|
143
|
-
@dummy = Dummy.new
|
144
|
-
@dummy.avatar = file
|
145
|
-
|
146
|
-
allow(@dummy).to receive(:new_record?).and_return(false)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
it "returns a replaced version for path" do
|
151
|
-
expect(@dummy.avatar.path).to match(/.+\/spaced_file\.png/)
|
152
|
-
end
|
153
|
-
|
154
|
-
it "returns a replaced version for url" do
|
155
|
-
expect(@dummy.avatar.url).to match(/.+\/spaced_file\.png/)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe "An attachment that uses Azure for storage and has a question mark in file name" do
|
160
|
-
before do
|
161
|
-
rebuild_model storage: :azure,
|
162
|
-
styles: { large: ['500x500#', :jpg] },
|
163
|
-
container: "container",
|
164
|
-
azure_credentials: {
|
165
|
-
'storage_access_key' => "54321"
|
166
|
-
}
|
167
|
-
|
168
|
-
stringio = stringy_file
|
169
|
-
class << stringio
|
170
|
-
def original_filename
|
171
|
-
"question?mark.png"
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
file = Paperclip.io_adapters.for(stringio)
|
176
|
-
|
177
|
-
@dummy = Dummy.new
|
178
|
-
@dummy.avatar = file
|
179
|
-
@dummy.save
|
180
|
-
|
181
|
-
allow(@dummy).to receive(:new_record?).and_return(false)
|
182
|
-
end
|
183
|
-
|
184
|
-
it "returns a replaced version for path" do
|
185
|
-
expect(@dummy.avatar.path).to match(/.+\/question_mark\.png/)
|
186
|
-
end
|
187
|
-
|
188
|
-
it "returns a replaced version for url" do
|
189
|
-
expect(@dummy.avatar.url).to match(/.+\/question_mark\.png/)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
describe ":asset_host path Interpolations" do
|
194
|
-
before do
|
195
|
-
rebuild_model storage: :azure,
|
196
|
-
azure_credentials: {},
|
197
|
-
container: "container",
|
198
|
-
path: ":attachment/:basename:dotextension",
|
199
|
-
url: ":asset_host"
|
200
|
-
@dummy = Dummy.new
|
201
|
-
@dummy.avatar = stringy_file
|
202
|
-
allow(@dummy).to receive(:new_record?).and_return(false)
|
203
|
-
end
|
204
|
-
|
205
|
-
it "returns a relative URL for Rails to calculate assets host" do
|
206
|
-
expect(@dummy.avatar.url).to match(%r{^avatars/data[^\.]})
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
describe "#expiring_url" do
|
211
|
-
before { @dummy = Dummy.new }
|
212
|
-
|
213
|
-
describe "with no attachment" do
|
214
|
-
before { expect(@dummy.avatar.exists?).to be_falsey }
|
215
|
-
|
216
|
-
it "returns the default URL" do
|
217
|
-
expect(@dummy.avatar.expiring_url).to eq(@dummy.avatar.url)
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'generates a url for a style when a file does not exist' do
|
221
|
-
expect(@dummy.avatar.expiring_url(3600, :thumb)).to eq(@dummy.avatar.url(:thumb))
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
describe "Generating a url with an expiration for each style" do
|
227
|
-
before do
|
228
|
-
rebuild_model storage: :azure,
|
229
|
-
azure_credentials: {
|
230
|
-
production: {
|
231
|
-
storage_account_name: 'prod_storage',
|
232
|
-
storage_access_key: 'YWNjZXNzLWtleQ==',
|
233
|
-
container: "prod_container"
|
234
|
-
},
|
235
|
-
development: {
|
236
|
-
storage_account_name: 'dev_storage',
|
237
|
-
storage_access_key: 'YWNjZXNzLWtleQ==',
|
238
|
-
container: "dev_container"
|
239
|
-
}
|
240
|
-
},
|
241
|
-
path: ":attachment/:style/:basename:dotextension"
|
242
|
-
|
243
|
-
rails_env("production") do
|
244
|
-
@dummy = Dummy.new
|
245
|
-
@dummy.avatar = stringy_file
|
246
|
-
end
|
247
|
-
|
248
|
-
allow(::Azure::Storage::Core::Auth::SharedAccessSignature).to receive(:new).and_call_original
|
249
|
-
allow(::Azure::Storage::Core::Auth::SharedAccessSignatureSigner).to receive(:new).and_call_original
|
250
|
-
end
|
251
|
-
|
252
|
-
it "generates a url for the thumb" do
|
253
|
-
rails_env("production") do
|
254
|
-
expect { @dummy.avatar.expiring_url(1800, :thumb) }.not_to raise_error
|
255
|
-
end
|
256
|
-
|
257
|
-
expect(::Azure::Storage::Core::Auth::SharedAccessSignature).to have_received(:new)
|
258
|
-
.with('prod_storage', anything)
|
259
|
-
end
|
260
|
-
|
261
|
-
it "generates a url for the default style" do
|
262
|
-
rails_env("production") do
|
263
|
-
expect { @dummy.avatar.expiring_url(1800) }.not_to raise_error
|
264
|
-
end
|
265
|
-
|
266
|
-
expect(::Azure::Storage::Core::Auth::SharedAccessSignature).to have_received(:new)
|
267
|
-
.with('prod_storage', anything)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
context "Parsing Azure credentials with a container in them" do
|
272
|
-
before do
|
273
|
-
rebuild_model storage: :azure,
|
274
|
-
azure_credentials: {
|
275
|
-
production: { container: "prod_container" },
|
276
|
-
development: { container: "dev_container" }
|
277
|
-
}
|
278
|
-
@dummy = Dummy.new
|
279
|
-
end
|
280
|
-
|
281
|
-
it "gets the right container in production" do
|
282
|
-
rails_env("production") do
|
283
|
-
expect(@dummy.avatar.container_name).to eq("prod_container")
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
it "gets the right container in development" do
|
288
|
-
rails_env("development") do
|
289
|
-
expect(@dummy.avatar.container_name).to eq("dev_container")
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
context "An attachment with Azure storage" do
|
295
|
-
before do
|
296
|
-
rebuild_model storage: :azure,
|
297
|
-
container: "testing",
|
298
|
-
path: ":attachment/:style/:basename:dotextension",
|
299
|
-
azure_credentials: {
|
300
|
-
storage_account_name: 'storage',
|
301
|
-
storage_access_key: storage_access_key
|
302
|
-
}
|
303
|
-
end
|
304
|
-
|
305
|
-
it "is extended by the Azure module" do
|
306
|
-
expect(Dummy.new.avatar).to be_a(Paperclip::Storage::Azure)
|
307
|
-
end
|
308
|
-
|
309
|
-
it "won't be extended by the Filesystem module" do
|
310
|
-
expect(Dummy.new.avatar).not_to be_a(Paperclip::Storage::Filesystem)
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
describe "An attachment with Azure storage and container defined as a Proc" do
|
315
|
-
before do
|
316
|
-
rebuild_model storage: :azure,
|
317
|
-
container: lambda { |attachment| "container_#{attachment.instance.other}" },
|
318
|
-
azure_credentials: {not: :important}
|
319
|
-
end
|
320
|
-
|
321
|
-
it "gets the right container name" do
|
322
|
-
expect(Dummy.new(other: 'a').avatar.container_name).to eq("container_a")
|
323
|
-
expect(Dummy.new(other: 'b').avatar.container_name).to eq("container_b")
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
context "An attachment with Azure storage and Azure credentials defined as a Proc" do
|
328
|
-
before do
|
329
|
-
rebuild_model storage: :azure,
|
330
|
-
container: {not: :important},
|
331
|
-
azure_credentials: lambda { |attachment|
|
332
|
-
Hash['storage_access_key' => "secret#{attachment.instance.other}"]
|
333
|
-
}
|
334
|
-
end
|
335
|
-
|
336
|
-
it "gets the right credentials" do
|
337
|
-
expect(Dummy.new(other: '1234').avatar.azure_credentials[:storage_access_key]).to eq("secret1234")
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
context "An attachment with Azure storage and Azure credentials in an unsupported manor" do
|
342
|
-
before do
|
343
|
-
rebuild_model storage: :azure,
|
344
|
-
container: "testing",
|
345
|
-
azure_credentials: ["unsupported"]
|
346
|
-
@dummy = Dummy.new
|
347
|
-
end
|
348
|
-
|
349
|
-
it "does not accept the credentials" do
|
350
|
-
expect { @dummy.avatar.azure_credentials }.to raise_error(ArgumentError)
|
351
|
-
end
|
352
|
-
end
|
353
|
-
|
354
|
-
context "An attachment with Azure storage and Azure credentials not supplied" do
|
355
|
-
before do
|
356
|
-
rebuild_model storage: :azure, container: "testing"
|
357
|
-
@dummy = Dummy.new
|
358
|
-
end
|
359
|
-
|
360
|
-
it "does not parse any credentials" do
|
361
|
-
expect(@dummy.avatar.azure_credentials).to eq({})
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
describe "with Azure credentials supplied as Pathname" do
|
366
|
-
before do
|
367
|
-
ENV['AZURE_CONTAINER'] = 'pathname_container'
|
368
|
-
ENV['AZURE_STORAGE_ACCOUNT'] = 'pathname_storage_account'
|
369
|
-
ENV['AZURE_STORAGE_ACCESS_KEY'] = storage_access_key
|
370
|
-
|
371
|
-
rails_env('test') do
|
372
|
-
rebuild_model storage: :azure,
|
373
|
-
azure_credentials: Pathname.new(fixture_file('azure.yml'))
|
374
|
-
|
375
|
-
Dummy.delete_all
|
376
|
-
@dummy = Dummy.new
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
it "parses the credentials" do
|
381
|
-
expect(@dummy.avatar.container_name).to eq('pathname_container')
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
|
-
describe "with Azure credentials in a YAML file" do
|
386
|
-
before do
|
387
|
-
ENV['AZURE_CONTAINER'] = 'pathname_container'
|
388
|
-
ENV['AZURE_STORAGE_ACCOUNT'] = 'pathname_storage_account'
|
389
|
-
ENV['AZURE_STORAGE_ACCESS_KEY'] = storage_access_key
|
390
|
-
|
391
|
-
rails_env('test') do
|
392
|
-
rebuild_model storage: :azure,
|
393
|
-
azure_credentials: File.new(fixture_file('azure.yml'))
|
394
|
-
|
395
|
-
Dummy.delete_all
|
396
|
-
|
397
|
-
@dummy = Dummy.new
|
398
|
-
end
|
399
|
-
end
|
400
|
-
|
401
|
-
it "runs the file through ERB" do
|
402
|
-
expect(@dummy.avatar.container_name).to eq('pathname_container')
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
describe "path is a proc" do
|
407
|
-
before do
|
408
|
-
rebuild_model storage: :azure,
|
409
|
-
path: ->(attachment) { attachment.instance.attachment_path }
|
410
|
-
|
411
|
-
@dummy = Dummy.new
|
412
|
-
@dummy.class_eval do
|
413
|
-
def attachment_path
|
414
|
-
'/some/dynamic/path'
|
415
|
-
end
|
416
|
-
end
|
417
|
-
@dummy.avatar = stringy_file
|
418
|
-
end
|
419
|
-
|
420
|
-
it "returns a correct path" do
|
421
|
-
expect(@dummy.avatar.path).to eq('/some/dynamic/path')
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
private
|
426
|
-
|
427
|
-
def rails_env(env)
|
428
|
-
stored_env, Rails.env = Rails.env, env
|
429
|
-
begin
|
430
|
-
yield
|
431
|
-
ensure
|
432
|
-
Rails.env = stored_env
|
433
|
-
end
|
434
|
-
end
|
435
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rspec'
|
3
|
-
require 'active_record'
|
4
|
-
require 'active_record/version'
|
5
|
-
require 'active_support'
|
6
|
-
require 'active_support/core_ext'
|
7
|
-
require 'ostruct'
|
8
|
-
require 'pathname'
|
9
|
-
require 'activerecord-import'
|
10
|
-
require 'simplecov'
|
11
|
-
require 'yaml'
|
12
|
-
require 'paperclip'
|
13
|
-
|
14
|
-
ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
|
15
|
-
|
16
|
-
module SimpleCov::Configuration
|
17
|
-
def clean_filters
|
18
|
-
@filters = []
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
SimpleCov.configure do
|
23
|
-
clean_filters
|
24
|
-
load_adapter 'test_frameworks'
|
25
|
-
end
|
26
|
-
|
27
|
-
ENV["COVERAGE"] && SimpleCov.start do
|
28
|
-
add_filter "/.rvm/"
|
29
|
-
end
|
30
|
-
|
31
|
-
$LOAD_PATH << File.join(ROOT, 'lib')
|
32
|
-
$LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
|
33
|
-
require File.join(ROOT, 'lib', 'paperclip-azure.rb')
|
34
|
-
|
35
|
-
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
36
|
-
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
37
|
-
ActiveRecord::Base.establish_connection(config['test'])
|
38
|
-
if ActiveRecord::VERSION::STRING >= "4.2" &&
|
39
|
-
ActiveRecord::VERSION::STRING < "5.0"
|
40
|
-
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
41
|
-
end
|
42
|
-
Paperclip.options[:logger] = ActiveRecord::Base.logger
|
43
|
-
|
44
|
-
Dir[File.join(ROOT, 'spec', 'support', '**', '*.rb')].each{|f| require f }
|
45
|
-
|
46
|
-
Rails = FakeRails.new('test', Pathname.new(ROOT).join('tmp'))
|
47
|
-
ActiveSupport::Deprecation.silenced = true
|
48
|
-
|
49
|
-
RSpec.configure do |config|
|
50
|
-
config.include ModelReconstruction
|
51
|
-
config.include TestData
|
52
|
-
config.extend VersionHelper
|
53
|
-
config.before(:all) do
|
54
|
-
rebuild_model
|
55
|
-
end
|
56
|
-
end
|
data/spec/support/fake_model.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
class FakeModel
|
2
|
-
attr_accessor(
|
3
|
-
:avatar_file_name,
|
4
|
-
:avatar_file_size,
|
5
|
-
:avatar_updated_at,
|
6
|
-
:avatar_content_type,
|
7
|
-
:avatar_fingerprint,
|
8
|
-
:id
|
9
|
-
)
|
10
|
-
|
11
|
-
def errors
|
12
|
-
@errors ||= []
|
13
|
-
end
|
14
|
-
|
15
|
-
def run_paperclip_callbacks name, *args
|
16
|
-
end
|
17
|
-
|
18
|
-
def valid?
|
19
|
-
errors.empty?
|
20
|
-
end
|
21
|
-
|
22
|
-
def new_record?
|
23
|
-
false
|
24
|
-
end
|
25
|
-
end
|
data/spec/support/fake_rails.rb
DELETED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
This is not an image.
|
@@ -1 +0,0 @@
|
|
1
|
-
<html></html>
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
paperclip!
|
Binary file
|
Binary file
|
@@ -1,24 +0,0 @@
|
|
1
|
-
class MockAttachment
|
2
|
-
attr_accessor :updated_at, :original_filename
|
3
|
-
attr_reader :options
|
4
|
-
|
5
|
-
def initialize(options = {})
|
6
|
-
@options = options
|
7
|
-
@model = options[:model]
|
8
|
-
@responds_to_updated_at = options[:responds_to_updated_at]
|
9
|
-
@updated_at = options[:updated_at]
|
10
|
-
@original_filename = options[:original_filename]
|
11
|
-
end
|
12
|
-
|
13
|
-
def instance
|
14
|
-
@model
|
15
|
-
end
|
16
|
-
|
17
|
-
def respond_to?(meth)
|
18
|
-
if meth.to_s == "updated_at"
|
19
|
-
@responds_to_updated_at || @updated_at
|
20
|
-
else
|
21
|
-
super
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
class MockInterpolator
|
2
|
-
def initialize(options = {})
|
3
|
-
@options = options
|
4
|
-
end
|
5
|
-
|
6
|
-
def interpolate(pattern, attachment, style_name)
|
7
|
-
@interpolated_pattern = pattern
|
8
|
-
@interpolated_attachment = attachment
|
9
|
-
@interpolated_style_name = style_name
|
10
|
-
@options[:result]
|
11
|
-
end
|
12
|
-
|
13
|
-
def has_interpolated_pattern?(pattern)
|
14
|
-
@interpolated_pattern == pattern
|
15
|
-
end
|
16
|
-
|
17
|
-
def has_interpolated_style_name?(style_name)
|
18
|
-
@interpolated_style_name == style_name
|
19
|
-
end
|
20
|
-
|
21
|
-
def has_interpolated_attachment?(attachment)
|
22
|
-
@interpolated_attachment == attachment
|
23
|
-
end
|
24
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
class MockUrlGeneratorBuilder
|
2
|
-
def initializer
|
3
|
-
end
|
4
|
-
|
5
|
-
def new(attachment)
|
6
|
-
@attachment = attachment
|
7
|
-
@attachment_options = @attachment.options
|
8
|
-
self
|
9
|
-
end
|
10
|
-
|
11
|
-
def for(style_name, options)
|
12
|
-
@generated_url_with_style_name = style_name
|
13
|
-
@generated_url_with_options = options
|
14
|
-
"hello"
|
15
|
-
end
|
16
|
-
|
17
|
-
def has_generated_url_with_options?(options)
|
18
|
-
# options.is_a_subhash_of(@generated_url_with_options)
|
19
|
-
options.inject(true) do |acc,(k,v)|
|
20
|
-
acc && @generated_url_with_options[k] == v
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def has_generated_url_with_style_name?(style_name)
|
25
|
-
@generated_url_with_style_name == style_name
|
26
|
-
end
|
27
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module ModelReconstruction
|
2
|
-
def reset_class class_name
|
3
|
-
ActiveRecord::Base.send(:include, Paperclip::Glue)
|
4
|
-
Object.send(:remove_const, class_name) rescue nil
|
5
|
-
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
|
6
|
-
|
7
|
-
klass.class_eval do
|
8
|
-
include Paperclip::Glue
|
9
|
-
end
|
10
|
-
|
11
|
-
klass.reset_column_information
|
12
|
-
klass.connection_pool.clear_table_cache!(klass.table_name) if klass.connection_pool.respond_to?(:clear_table_cache!)
|
13
|
-
|
14
|
-
if klass.connection.respond_to?(:schema_cache)
|
15
|
-
if ActiveRecord::VERSION::STRING >= "5.0"
|
16
|
-
klass.connection.schema_cache.clear_data_source_cache!(klass.table_name)
|
17
|
-
else
|
18
|
-
klass.connection.schema_cache.clear_table_cache!(klass.table_name)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
klass
|
23
|
-
end
|
24
|
-
|
25
|
-
def reset_table table_name, &block
|
26
|
-
block ||= lambda { |table| true }
|
27
|
-
ActiveRecord::Base.connection.create_table :dummies, {force: true}, &block
|
28
|
-
end
|
29
|
-
|
30
|
-
def modify_table table_name, &block
|
31
|
-
ActiveRecord::Base.connection.change_table :dummies, &block
|
32
|
-
end
|
33
|
-
|
34
|
-
def rebuild_model options = {}
|
35
|
-
ActiveRecord::Base.connection.create_table :dummies, force: true do |table|
|
36
|
-
table.column :title, :string
|
37
|
-
table.column :other, :string
|
38
|
-
table.column :avatar_file_name, :string
|
39
|
-
table.column :avatar_content_type, :string
|
40
|
-
table.column :avatar_file_size, :integer
|
41
|
-
table.column :avatar_updated_at, :datetime
|
42
|
-
table.column :avatar_fingerprint, :string
|
43
|
-
end
|
44
|
-
rebuild_class options
|
45
|
-
end
|
46
|
-
|
47
|
-
def rebuild_class options = {}
|
48
|
-
reset_class("Dummy").tap do |klass|
|
49
|
-
klass.has_attached_file :avatar, options
|
50
|
-
klass.do_not_validate_attachment_file_type :avatar
|
51
|
-
Paperclip.reset_duplicate_clash_check!
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def rebuild_meta_class_of obj, options = {}
|
56
|
-
meta_class_of(obj).tap do |metaklass|
|
57
|
-
metaklass.has_attached_file :avatar, options
|
58
|
-
metaklass.do_not_validate_attachment_file_type :avatar
|
59
|
-
Paperclip.reset_duplicate_clash_check!
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def meta_class_of(obj)
|
64
|
-
class << obj
|
65
|
-
self
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/spec/support/test_data.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module TestData
|
2
|
-
def attachment(options={})
|
3
|
-
Paperclip::Attachment.new(:avatar, FakeModel.new, options)
|
4
|
-
end
|
5
|
-
|
6
|
-
def stringy_file
|
7
|
-
StringIO.new('.\n')
|
8
|
-
end
|
9
|
-
|
10
|
-
def fixture_file(filename)
|
11
|
-
File.join(File.dirname(__FILE__), 'fixtures', filename)
|
12
|
-
end
|
13
|
-
end
|