asset_cloud 2.7.1 → 2.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +20 -5
- data/.github/workflows/cla.yml +22 -0
- data/.rubocop.yml +3 -1
- data/Gemfile +5 -3
- data/History.md +4 -0
- data/Rakefile +18 -16
- data/asset_cloud.gemspec +19 -18
- data/dev.yml +1 -1
- data/lib/asset_cloud/asset.rb +17 -13
- data/lib/asset_cloud/asset_extension.rb +27 -15
- data/lib/asset_cloud/base.rb +77 -72
- data/lib/asset_cloud/bucket.rb +5 -2
- data/lib/asset_cloud/buckets/active_record_bucket.rb +16 -14
- data/lib/asset_cloud/buckets/blackhole_bucket.rb +2 -0
- data/lib/asset_cloud/buckets/bucket_chain.rb +38 -31
- data/lib/asset_cloud/buckets/file_system_bucket.rb +14 -15
- data/lib/asset_cloud/buckets/gcs_bucket.rb +6 -8
- data/lib/asset_cloud/buckets/invalid_bucket.rb +9 -6
- data/lib/asset_cloud/buckets/memory_bucket.rb +7 -4
- data/lib/asset_cloud/buckets/s3_bucket.rb +11 -8
- data/lib/asset_cloud/buckets/versioned_memory_bucket.rb +4 -2
- data/lib/asset_cloud/callbacks.rb +7 -3
- data/lib/asset_cloud/free_key_locator.rb +6 -6
- data/lib/asset_cloud/metadata.rb +11 -7
- data/lib/asset_cloud/validations.rb +9 -5
- data/lib/asset_cloud.rb +23 -21
- data/spec/active_record_bucket_spec.rb +27 -26
- data/spec/asset_cloud/metadata_spec.rb +4 -2
- data/spec/asset_extension_spec.rb +17 -16
- data/spec/asset_spec.rb +27 -21
- data/spec/base_spec.rb +93 -92
- data/spec/blackhole_bucket_spec.rb +12 -11
- data/spec/bucket_chain_spec.rb +61 -56
- data/spec/bucket_spec.rb +6 -5
- data/spec/callbacks_spec.rb +41 -39
- data/spec/file_system_spec.rb +25 -24
- data/spec/find_free_key_spec.rb +16 -17
- data/spec/gcs_bucket_remote_spec.rb +23 -22
- data/spec/gcs_bucket_spec.rb +48 -60
- data/spec/memory_bucket_spec.rb +12 -11
- data/spec/mock_s3_interface.rb +17 -6
- data/spec/remote_s3_bucket_spec.rb +31 -28
- data/spec/s3_bucket_spec.rb +19 -17
- data/spec/spec_helper.rb +8 -7
- data/spec/validations_spec.rb +13 -12
- data/spec/versioned_memory_bucket_spec.rb +11 -10
- metadata +9 -32
- data/.github/probots.yml +0 -2
- data/.rubocop_todo.yml +0 -326
data/spec/base_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
class SpecialAsset < AssetCloud::Asset
|
5
6
|
end
|
@@ -16,182 +17,182 @@ end
|
|
16
17
|
class BasicCloud < AssetCloud::Base
|
17
18
|
bucket :special, AssetCloud::MemoryBucket, asset_class: SpecialAsset
|
18
19
|
bucket :conditional, AssetCloud::MemoryBucket, asset_class: proc { |key|
|
19
|
-
LiquidAsset if key.ends_with?(
|
20
|
+
LiquidAsset if key.ends_with?(".liquid")
|
20
21
|
}
|
21
22
|
bucket :broken, BrokenBucket, asset_class: AssetCloud::Asset
|
22
23
|
end
|
23
24
|
|
24
25
|
describe BasicCloud do
|
25
|
-
directory = File.dirname(__FILE__) +
|
26
|
+
directory = File.dirname(__FILE__) + "/files"
|
26
27
|
|
27
28
|
before do
|
28
|
-
@fs = BasicCloud.new(directory,
|
29
|
+
@fs = BasicCloud.new(directory, "http://assets/files")
|
29
30
|
end
|
30
31
|
|
31
32
|
it "should raise invalid bucket if none is given" do
|
32
|
-
expect(@fs[
|
33
|
+
expect(@fs["image.jpg"].exist?).to(eq(false))
|
33
34
|
end
|
34
35
|
|
35
36
|
it "should be backed by a file system bucket" do
|
36
|
-
expect(@fs[
|
37
|
+
expect(@fs["products/key.txt"].exist?).to(eq(true))
|
37
38
|
end
|
38
39
|
|
39
40
|
it "should raise when listing non existing buckets" do
|
40
|
-
expect(@fs.ls(
|
41
|
+
expect(@fs.ls("products")).to(eq([AssetCloud::Asset.new(@fs, "products/key.txt")]))
|
41
42
|
end
|
42
43
|
|
43
44
|
it "should allow you to create new assets" do
|
44
|
-
obj = @fs.build(
|
45
|
+
obj = @fs.build("new_file.test")
|
45
46
|
expect(obj).to(be_an_instance_of(AssetCloud::Asset))
|
46
47
|
expect(obj.cloud).to(be_an_instance_of(BasicCloud))
|
47
48
|
end
|
48
49
|
|
49
50
|
it "should raise error when using with minus relative or absolute paths" do
|
50
|
-
expect { @fs[
|
51
|
-
expect { @fs[
|
52
|
-
expect { @fs[
|
53
|
-
expect { @fs[
|
51
|
+
expect { @fs["../test"] }.to(raise_error(AssetCloud::IllegalPath))
|
52
|
+
expect { @fs["/test"] }.to(raise_error(AssetCloud::IllegalPath))
|
53
|
+
expect { @fs[".../test"] }.to(raise_error(AssetCloud::IllegalPath))
|
54
|
+
expect { @fs["./test"] }.to(raise_error(AssetCloud::IllegalPath))
|
54
55
|
end
|
55
56
|
|
56
57
|
it "should raise error when filename has trailing period" do
|
57
|
-
expect { @fs[
|
58
|
-
expect { @fs[
|
59
|
-
expect { @fs[
|
60
|
-
expect { @fs[
|
61
|
-
expect { @fs[
|
58
|
+
expect { @fs["test."] }.to(raise_error(AssetCloud::IllegalPath))
|
59
|
+
expect { @fs["/test/testfile."] }.to(raise_error(AssetCloud::IllegalPath))
|
60
|
+
expect { @fs["test/directory/."] }.to(raise_error(AssetCloud::IllegalPath))
|
61
|
+
expect { @fs["/test/testfile ."] }.to(raise_error(AssetCloud::IllegalPath))
|
62
|
+
expect { @fs["test/directory /."] }.to(raise_error(AssetCloud::IllegalPath))
|
62
63
|
end
|
63
64
|
|
64
65
|
it "should raise error when filename ends with space" do
|
65
|
-
expect { @fs[
|
66
|
-
expect { @fs[
|
67
|
-
expect { @fs[
|
68
|
-
expect { @fs[
|
69
|
-
expect { @fs[
|
70
|
-
expect { @fs[
|
66
|
+
expect { @fs["test "] }.to(raise_error(AssetCloud::IllegalPath))
|
67
|
+
expect { @fs["/test/testfile "] }.to(raise_error(AssetCloud::IllegalPath))
|
68
|
+
expect { @fs["test/directory/ "] }.to(raise_error(AssetCloud::IllegalPath))
|
69
|
+
expect { @fs["test. "] }.to(raise_error(AssetCloud::IllegalPath))
|
70
|
+
expect { @fs["/test/testfile. "] }.to(raise_error(AssetCloud::IllegalPath))
|
71
|
+
expect { @fs["test/directory/. "] }.to(raise_error(AssetCloud::IllegalPath))
|
71
72
|
end
|
72
73
|
|
73
74
|
it "should raise error when filename ends with slash" do
|
74
|
-
expect { @fs[
|
75
|
-
expect { @fs[
|
76
|
-
expect { @fs[
|
77
|
-
expect { @fs[
|
78
|
-
expect { @fs[
|
75
|
+
expect { @fs["test/"] }.to(raise_error(AssetCloud::IllegalPath))
|
76
|
+
expect { @fs["test/directory/"] }.to(raise_error(AssetCloud::IllegalPath))
|
77
|
+
expect { @fs["test /"] }.to(raise_error(AssetCloud::IllegalPath))
|
78
|
+
expect { @fs["/test/testfile /"] }.to(raise_error(AssetCloud::IllegalPath))
|
79
|
+
expect { @fs["test/directory//"] }.to(raise_error(AssetCloud::IllegalPath))
|
79
80
|
end
|
80
81
|
|
81
82
|
it "should raise error when using with minus relative even after another directory" do
|
82
|
-
expect { @fs[
|
83
|
-
expect { @fs[
|
84
|
-
expect { @fs[
|
83
|
+
expect { @fs["test/../test"] }.to(raise_error(AssetCloud::IllegalPath))
|
84
|
+
expect { @fs["test/../../test"] }.to(raise_error(AssetCloud::IllegalPath))
|
85
|
+
expect { @fs["test/../../../test"] }.to(raise_error(AssetCloud::IllegalPath))
|
85
86
|
end
|
86
87
|
|
87
88
|
it "should raise an error when using names with combinations of '.' and ' '" do
|
88
|
-
expect { @fs[
|
89
|
-
expect { @fs[
|
90
|
-
expect { @fs[
|
89
|
+
expect { @fs["test. . . .. ... .. . "] }.to(raise_error(AssetCloud::IllegalPath))
|
90
|
+
expect { @fs["test. ."] }.to(raise_error(AssetCloud::IllegalPath))
|
91
|
+
expect { @fs["test. .test2"] }.to(raise_error(AssetCloud::IllegalPath))
|
91
92
|
end
|
92
93
|
|
93
94
|
it "should allow filenames with repeating dots" do
|
94
|
-
@fs[
|
95
|
-
@fs[
|
96
|
-
@fs[
|
95
|
+
@fs["test..jpg"]
|
96
|
+
@fs["assets/T.T..jpg"]
|
97
|
+
@fs["test/assets/1234123412341234_obj_description..14...58......v8...._2134123412341234.jpg"]
|
97
98
|
end
|
98
99
|
|
99
100
|
it "should allow filenames with repeating underscores" do
|
100
|
-
@fs[
|
101
|
-
@fs[
|
102
|
-
@fs[
|
101
|
+
@fs["test__jpg"]
|
102
|
+
@fs["assets/T__T..jpg"]
|
103
|
+
@fs["test/assets/1234123412341234_obj_description..14...58......v8...__2134123412341234.jpg"]
|
103
104
|
end
|
104
105
|
|
105
106
|
it "should allow filenames with various bracket arragements" do
|
106
|
-
@fs[
|
107
|
-
@fs[
|
108
|
-
@fs[
|
107
|
+
@fs["test[1].jpg"]
|
108
|
+
@fs["test[1]"]
|
109
|
+
@fs["[test].jpg"]
|
109
110
|
end
|
110
111
|
|
111
112
|
it "should not raise an error when using directory names with spaces" do
|
112
|
-
@fs[
|
113
|
+
@fs["files/ass ets/.DS_Store"]
|
113
114
|
end
|
114
115
|
|
115
116
|
it "should not raise_error when using unusual but valid filenames" do
|
116
|
-
@fs[
|
117
|
-
@fs[
|
118
|
-
@fs[
|
119
|
-
@fs[
|
120
|
-
@fs[
|
121
|
-
@fs[
|
122
|
-
@fs[
|
117
|
+
@fs[".DS_Store"]
|
118
|
+
@fs["photograph.g"]
|
119
|
+
@fs["_testfilename"]
|
120
|
+
@fs["assets/.DS_Store"]
|
121
|
+
@fs["assets/photograph.g"]
|
122
|
+
@fs["a/_testfilename"]
|
123
|
+
@fs["a"]
|
123
124
|
end
|
124
125
|
|
125
126
|
it "should allow sensible relative filenames" do
|
126
|
-
@fs[
|
127
|
-
@fs[
|
128
|
-
@fs[
|
129
|
-
@fs[
|
130
|
-
@fs[
|
127
|
+
@fs["assets/rails_logo.gif"]
|
128
|
+
@fs["assets/rails_logo"]
|
129
|
+
@fs["assets/rails-2.gif"]
|
130
|
+
@fs["assets/223434.gif"]
|
131
|
+
@fs["files/1.JPG"]
|
131
132
|
end
|
132
133
|
|
133
134
|
it "should compute complete urls to assets" do
|
134
|
-
expect(@fs.url_for(
|
135
|
+
expect(@fs.url_for("products/[key] with spaces.txt?foo=1&bar=2")).to(eq("http://assets/files/products/[key]%20with%20spaces.txt?foo=1&bar=2"))
|
135
136
|
end
|
136
137
|
|
137
138
|
describe "#find" do
|
138
139
|
it "should return the appropriate asset when one exists" do
|
139
|
-
asset = @fs.find(
|
140
|
-
expect(asset.key).to(eq(
|
141
|
-
expect(asset.value).to(eq(
|
140
|
+
asset = @fs.find("products/key.txt")
|
141
|
+
expect(asset.key).to(eq("products/key.txt"))
|
142
|
+
expect(asset.value).to(eq("value"))
|
142
143
|
end
|
143
144
|
it "should raise AssetNotFoundError when the asset doesn't exist" do
|
144
|
-
expect { @fs.find(
|
145
|
+
expect { @fs.find("products/not-there.txt") }.to(raise_error(AssetCloud::AssetNotFoundError))
|
145
146
|
end
|
146
147
|
end
|
147
148
|
|
148
149
|
describe "#[]" do
|
149
150
|
it "should return the appropriate asset when one exists" do
|
150
|
-
asset = @fs[
|
151
|
-
expect(asset.key).to(eq(
|
152
|
-
expect(asset.value).to(eq(
|
151
|
+
asset = @fs["products/key.txt"]
|
152
|
+
expect(asset.key).to(eq("products/key.txt"))
|
153
|
+
expect(asset.value).to(eq("value"))
|
153
154
|
end
|
154
155
|
it "should not raise any errors when the asset doesn't exist" do
|
155
|
-
expect { @fs[
|
156
|
+
expect { @fs["products/not-there.txt"] }.not_to(raise_error)
|
156
157
|
end
|
157
158
|
end
|
158
159
|
|
159
160
|
describe "#move" do
|
160
161
|
it "should return move a resource" do
|
161
|
-
asset = @fs[
|
162
|
-
expect(asset.key).to(eq(
|
163
|
-
expect(asset.value).to(eq(
|
164
|
-
@fs.move(
|
165
|
-
new_asset = @fs[
|
166
|
-
expect(new_asset.key).to(eq(
|
167
|
-
expect(new_asset.value).to(eq(
|
168
|
-
expect { @fs[
|
169
|
-
@fs.move(
|
162
|
+
asset = @fs["products/key.txt"]
|
163
|
+
expect(asset.key).to(eq("products/key.txt"))
|
164
|
+
expect(asset.value).to(eq("value"))
|
165
|
+
@fs.move("products/key.txt", "products/key2.txt")
|
166
|
+
new_asset = @fs["products/key2.txt"]
|
167
|
+
expect(new_asset.key).to(eq("products/key2.txt"))
|
168
|
+
expect(new_asset.value).to(eq("value"))
|
169
|
+
expect { @fs["products/key.txt"].value }.to(raise_error(AssetCloud::AssetNotFoundError))
|
170
|
+
@fs.move("products/key2.txt", "products/key.txt")
|
170
171
|
end
|
171
172
|
end
|
172
173
|
|
173
174
|
describe "#[]=" do
|
174
175
|
it "should write through the Asset object (and thus run any callbacks on the asset)" do
|
175
176
|
special_asset = double(:special_asset)
|
176
|
-
expect(special_asset).to(receive(:value=).with(
|
177
|
+
expect(special_asset).to(receive(:value=).with("fancy fancy!"))
|
177
178
|
expect(special_asset).to(receive(:store))
|
178
179
|
expect(SpecialAsset).to(receive(:at).and_return(special_asset))
|
179
|
-
@fs[
|
180
|
+
@fs["special/fancy.txt"] = "fancy fancy!"
|
180
181
|
end
|
181
182
|
end
|
182
183
|
|
183
184
|
describe "#bucket" do
|
184
185
|
it "should allow specifying a class to use for assets in this bucket" do
|
185
|
-
expect(@fs[
|
186
|
-
expect(@fs[
|
186
|
+
expect(@fs["assets/rails_logo.gif"]).to(be_instance_of(AssetCloud::Asset))
|
187
|
+
expect(@fs["special/fancy.txt"]).to(be_instance_of(SpecialAsset))
|
187
188
|
|
188
|
-
expect(@fs.build(
|
189
|
-
expect(@fs.build(
|
189
|
+
expect(@fs.build("assets/foo")).to(be_instance_of(AssetCloud::Asset))
|
190
|
+
expect(@fs.build("special/foo")).to(be_instance_of(SpecialAsset))
|
190
191
|
end
|
191
192
|
|
192
193
|
it "should allow specifying a proc that determines the class to use, using the default bucket when returning nil" do
|
193
|
-
expect(@fs.build(
|
194
|
-
expect(@fs.build(
|
194
|
+
expect(@fs.build("conditional/default.js")).to(be_instance_of(AssetCloud::Asset))
|
195
|
+
expect(@fs.build("conditional/better.liquid")).to(be_instance_of(LiquidAsset))
|
195
196
|
end
|
196
197
|
|
197
198
|
it "should raise " do
|
@@ -202,30 +203,30 @@ describe BasicCloud do
|
|
202
203
|
describe "write!" do
|
203
204
|
it "should write through the Asset object (and thus run any callbacks on the asset)" do
|
204
205
|
special_asset = double(:special_asset)
|
205
|
-
expect(special_asset).to(receive(:value=).with(
|
206
|
+
expect(special_asset).to(receive(:value=).with("fancy fancy!"))
|
206
207
|
expect(special_asset).to(receive(:store!))
|
207
208
|
expect(SpecialAsset).to(receive(:at).and_return(special_asset))
|
208
|
-
@fs.write!(
|
209
|
+
@fs.write!("special/fancy.txt", "fancy fancy!")
|
209
210
|
end
|
210
211
|
|
211
212
|
it "should raise AssetNotSaved when write fails" do
|
212
|
-
expect { @fs.write!(
|
213
|
+
expect { @fs.write!("broken/file.txt", "n/a") }.to(raise_error(AssetCloud::AssetNotSaved))
|
213
214
|
end
|
214
215
|
end
|
215
216
|
|
216
217
|
describe "MATCH_BUCKET" do
|
217
218
|
it "should match following stuff " do
|
218
|
-
|
219
|
-
expect(Regexp.last_match(1)).to(eq(
|
219
|
+
"products/key.txt" =~ AssetCloud::Base::MATCH_BUCKET
|
220
|
+
expect(Regexp.last_match(1)).to(eq("products"))
|
220
221
|
|
221
|
-
|
222
|
-
expect(Regexp.last_match(1)).to(eq(
|
222
|
+
"products/subpath/key.txt" =~ AssetCloud::Base::MATCH_BUCKET
|
223
|
+
expect(Regexp.last_match(1)).to(eq("products"))
|
223
224
|
|
224
|
-
|
225
|
+
"key.txt" =~ AssetCloud::Base::MATCH_BUCKET
|
225
226
|
expect(Regexp.last_match(1)).to(eq(nil))
|
226
227
|
|
227
|
-
|
228
|
-
expect(Regexp.last_match(1)).to(eq(
|
228
|
+
"products" =~ AssetCloud::Base::MATCH_BUCKET
|
229
|
+
expect(Regexp.last_match(1)).to(eq("products"))
|
229
230
|
end
|
230
231
|
end
|
231
232
|
end
|
@@ -1,42 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
class BlackholeCloud < AssetCloud::Base
|
5
6
|
bucket AssetCloud::BlackholeBucket
|
6
7
|
end
|
7
8
|
|
8
9
|
describe BlackholeCloud do
|
9
|
-
directory = File.dirname(__FILE__) +
|
10
|
+
directory = File.dirname(__FILE__) + "/files"
|
10
11
|
|
11
12
|
before do
|
12
|
-
@fs = BlackholeCloud.new(directory,
|
13
|
+
@fs = BlackholeCloud.new(directory, "http://assets/files")
|
13
14
|
end
|
14
15
|
|
15
16
|
it "should allow access to files using the [] operator" do
|
16
|
-
@fs[
|
17
|
+
@fs["tmp/image.jpg"]
|
17
18
|
end
|
18
19
|
|
19
20
|
it "should return nil for non existent files" do
|
20
|
-
expect(@fs[
|
21
|
+
expect(@fs["tmp/image.jpg"].exist?).to(eq(false))
|
21
22
|
end
|
22
23
|
|
23
24
|
it "should still return nil, even if you wrote something there" do
|
24
|
-
@fs[
|
25
|
-
expect(@fs[
|
25
|
+
@fs["tmp/image.jpg"] = "test"
|
26
|
+
expect(@fs["tmp/image.jpg"].exist?).to(eq(false))
|
26
27
|
end
|
27
28
|
|
28
29
|
describe "when using a sub path" do
|
29
30
|
it "should allow access to files using the [] operator" do
|
30
|
-
@fs[
|
31
|
+
@fs["tmp/image.jpg"]
|
31
32
|
end
|
32
33
|
|
33
34
|
it "should return nil for non existent files" do
|
34
|
-
expect(@fs[
|
35
|
+
expect(@fs["tmp/image.jpg"].exist?).to(eq(false))
|
35
36
|
end
|
36
37
|
|
37
38
|
it "should still return nil, even if you wrote something there" do
|
38
|
-
@fs[
|
39
|
-
expect(@fs[
|
39
|
+
@fs["tmp/image.jpg"] = "test"
|
40
|
+
expect(@fs["tmp/image.jpg"].exist?).to(eq(false))
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
data/spec/bucket_chain_spec.rb
CHANGED
@@ -1,93 +1,98 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
2
|
|
4
|
-
|
5
|
-
bucket :stuff, AssetCloud::BucketChain.chain(AssetCloud::MemoryBucket,
|
6
|
-
AssetCloud::MemoryBucket,
|
7
|
-
AssetCloud::FileSystemBucket)
|
3
|
+
require "spec_helper"
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
class ChainedCloud < AssetCloud::Base
|
6
|
+
bucket :stuff, AssetCloud::BucketChain.chain(
|
7
|
+
AssetCloud::MemoryBucket,
|
8
|
+
AssetCloud::MemoryBucket,
|
9
|
+
AssetCloud::FileSystemBucket,
|
10
|
+
)
|
11
|
+
|
12
|
+
bucket :versioned_stuff, AssetCloud::BucketChain.chain(
|
13
|
+
AssetCloud::FileSystemBucket,
|
14
|
+
AssetCloud::VersionedMemoryBucket,
|
15
|
+
AssetCloud::MemoryBucket,
|
16
|
+
)
|
12
17
|
end
|
13
18
|
|
14
19
|
describe AssetCloud::BucketChain do
|
15
|
-
directory = File.dirname(__FILE__) +
|
20
|
+
directory = File.dirname(__FILE__) + "/files"
|
16
21
|
|
17
22
|
before(:each) do
|
18
|
-
@cloud = ChainedCloud.new(directory,
|
23
|
+
@cloud = ChainedCloud.new(directory, "http://assets/files")
|
19
24
|
@bucket_chain = @cloud.buckets[:stuff]
|
20
25
|
@chained_buckets = @bucket_chain.chained_buckets
|
21
|
-
@chained_buckets.each { |b| b.ls(
|
26
|
+
@chained_buckets.each { |b| b.ls("stuff").each(&:delete) }
|
22
27
|
|
23
28
|
@versioned_stuff = @cloud.buckets[:versioned_stuff]
|
24
29
|
end
|
25
30
|
|
26
31
|
describe ".chain" do
|
27
|
-
it
|
32
|
+
it "should take multiple Bucket classes and return a new Bucket class" do
|
28
33
|
expect(@bucket_chain).to(be_a_kind_of(AssetCloud::BucketChain))
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
32
37
|
describe "#write" do
|
33
|
-
it
|
38
|
+
it "should write to each sub-bucket when everything is kosher and return the result of the first write" do
|
34
39
|
@chained_buckets.each do |bucket|
|
35
|
-
expect(bucket).to(receive(:write).with(
|
40
|
+
expect(bucket).to(receive(:write).with("stuff/foo", "successful creation").and_return("successful creation"))
|
36
41
|
end
|
37
42
|
|
38
|
-
expect(@bucket_chain.write(
|
43
|
+
expect(@bucket_chain.write("stuff/foo", "successful creation")).to(eq("successful creation"))
|
39
44
|
end
|
40
|
-
it
|
41
|
-
expect(@chained_buckets.last).to(receive(:write).with(
|
45
|
+
it "should roll back creation-writes and re-raise an error when a bucket raises one" do
|
46
|
+
expect(@chained_buckets.last).to(receive(:write).with("stuff/foo", "unsuccessful creation").and_raise("hell"))
|
42
47
|
@chained_buckets[0..-2].each do |bucket|
|
43
|
-
expect(bucket).to(receive(:write).with(
|
44
|
-
expect(bucket).to(receive(:delete).with(
|
48
|
+
expect(bucket).to(receive(:write).with("stuff/foo", "unsuccessful creation").and_return(true))
|
49
|
+
expect(bucket).to(receive(:delete).with("stuff/foo").and_return(true))
|
45
50
|
end
|
46
51
|
|
47
|
-
expect { @bucket_chain.write(
|
52
|
+
expect { @bucket_chain.write("stuff/foo", "unsuccessful creation") }.to(raise_error(RuntimeError))
|
48
53
|
end
|
49
|
-
it
|
50
|
-
@bucket_chain.write(
|
54
|
+
it "should roll back update-writes and re-raise an error when a bucket raises one" do
|
55
|
+
@bucket_chain.write("stuff/foo", "original value")
|
51
56
|
|
52
|
-
expect(@chained_buckets.last).to(receive(:write).with(
|
57
|
+
expect(@chained_buckets.last).to(receive(:write).with("stuff/foo", "new value").and_raise("hell"))
|
53
58
|
|
54
|
-
expect { @bucket_chain.write(
|
59
|
+
expect { @bucket_chain.write("stuff/foo", "new value") }.to(raise_error(RuntimeError))
|
55
60
|
@chained_buckets.each do |bucket|
|
56
|
-
expect(bucket.read(
|
61
|
+
expect(bucket.read("stuff/foo")).to(eq("original value"))
|
57
62
|
end
|
58
63
|
end
|
59
64
|
end
|
60
65
|
|
61
66
|
describe "#delete" do
|
62
|
-
it
|
63
|
-
@bucket_chain.write(
|
67
|
+
it "should delete from each sub-bucket when everything is kosher" do
|
68
|
+
@bucket_chain.write("stuff/foo", "successful deletion comin' up")
|
64
69
|
|
65
70
|
@chained_buckets.each do |bucket|
|
66
|
-
expect(bucket).to(receive(:delete).with(
|
71
|
+
expect(bucket).to(receive(:delete).with("stuff/foo").and_return(true))
|
67
72
|
end
|
68
73
|
|
69
|
-
@bucket_chain.delete(
|
74
|
+
@bucket_chain.delete("stuff/foo")
|
70
75
|
end
|
71
|
-
it
|
72
|
-
@bucket_chain.write(
|
76
|
+
it "should roll back deletions and re-raise an error when a bucket raises one" do
|
77
|
+
@bucket_chain.write("stuff/foo", "this deletion will fail")
|
73
78
|
|
74
|
-
expect(@chained_buckets.last).to(receive(:delete).with(
|
79
|
+
expect(@chained_buckets.last).to(receive(:delete).with("stuff/foo").and_raise("hell"))
|
75
80
|
@chained_buckets[0..-2].each do |bucket|
|
76
|
-
expect(bucket).to(receive(:delete).with(
|
77
|
-
expect(bucket).to(receive(:write).with(
|
81
|
+
expect(bucket).to(receive(:delete).with("stuff/foo").and_return(true))
|
82
|
+
expect(bucket).to(receive(:write).with("stuff/foo", "this deletion will fail").and_return(true))
|
78
83
|
end
|
79
84
|
|
80
|
-
expect { @bucket_chain.delete(
|
85
|
+
expect { @bucket_chain.delete("stuff/foo") }.to(raise_error(RuntimeError))
|
81
86
|
end
|
82
87
|
end
|
83
88
|
|
84
89
|
describe "#read" do
|
85
|
-
it
|
86
|
-
expect(@chained_buckets[0]).to(receive(:read).with(
|
90
|
+
it "should read from only the first available sub-bucket" do
|
91
|
+
expect(@chained_buckets[0]).to(receive(:read).with("stuff/foo").and_raise(NotImplementedError))
|
87
92
|
expect(@chained_buckets[0]).to(receive(:ls).with(nil).and_raise(NoMethodError))
|
88
93
|
expect(@chained_buckets[0]).to(receive(:stat).and_return(:metadata))
|
89
94
|
|
90
|
-
expect(@chained_buckets[1]).to(receive(:read).with(
|
95
|
+
expect(@chained_buckets[1]).to(receive(:read).with("stuff/foo").and_return("bar"))
|
91
96
|
expect(@chained_buckets[1]).to(receive(:ls).with(nil).and_return(:some_assets))
|
92
97
|
expect(@chained_buckets[1]).not_to(receive(:stat))
|
93
98
|
|
@@ -97,59 +102,59 @@ describe AssetCloud::BucketChain do
|
|
97
102
|
expect(bucket).not_to(receive(:stat))
|
98
103
|
end
|
99
104
|
|
100
|
-
expect(@bucket_chain.read(
|
105
|
+
expect(@bucket_chain.read("stuff/foo")).to(eq("bar"))
|
101
106
|
expect(@bucket_chain.ls).to(eq(:some_assets))
|
102
107
|
expect(@bucket_chain.stat).to(eq(:metadata))
|
103
108
|
end
|
104
109
|
end
|
105
110
|
|
106
111
|
describe "#read_version" do
|
107
|
-
it
|
112
|
+
it "should read from only the first available sub-bucket" do
|
108
113
|
buckets = @versioned_stuff.chained_buckets
|
109
114
|
|
110
|
-
expect(buckets[1]).to(receive(:read_version).with(
|
115
|
+
expect(buckets[1]).to(receive(:read_version).with("stuff/foo", 3).and_return("bar"))
|
111
116
|
expect(buckets.last).not_to(receive(:read_version))
|
112
117
|
|
113
|
-
expect(@versioned_stuff.read_version(
|
118
|
+
expect(@versioned_stuff.read_version("stuff/foo", 3)).to(eq("bar"))
|
114
119
|
end
|
115
120
|
end
|
116
121
|
|
117
122
|
describe "#versions" do
|
118
|
-
it
|
123
|
+
it "should read from only the first available sub-bucket" do
|
119
124
|
buckets = @versioned_stuff.chained_buckets
|
120
125
|
|
121
|
-
expect(buckets[1]).to(receive(:versions).with(
|
126
|
+
expect(buckets[1]).to(receive(:versions).with("versioned_stuff/foo").and_return([1, 2, 3]))
|
122
127
|
expect(buckets.last).not_to(receive(:versions))
|
123
128
|
|
124
|
-
expect(@versioned_stuff.versions(
|
129
|
+
expect(@versioned_stuff.versions("versioned_stuff/foo")).to(eq([1, 2, 3]))
|
125
130
|
end
|
126
131
|
end
|
127
132
|
|
128
133
|
describe "with versioned buckets" do
|
129
|
-
it
|
130
|
-
|
131
|
-
@cloud[
|
134
|
+
it "should store and retrieve versions seamlessly" do
|
135
|
+
["one", "two", "three"].each do |content|
|
136
|
+
@cloud["versioned_stuff/foo"] = content
|
132
137
|
end
|
133
|
-
asset = @cloud[
|
134
|
-
expect(asset.value).to(eq(
|
135
|
-
expect(asset.rollback(1).value).to(eq(
|
138
|
+
asset = @cloud["versioned_stuff/foo"]
|
139
|
+
expect(asset.value).to(eq("three"))
|
140
|
+
expect(asset.rollback(1).value).to(eq("one"))
|
136
141
|
expect(asset.versions).to(eq([1, 2, 3]))
|
137
|
-
asset.value =
|
142
|
+
asset.value = "four"
|
138
143
|
asset.store
|
139
144
|
expect(asset.versions).to(eq([1, 2, 3, 4]))
|
140
145
|
end
|
141
146
|
end
|
142
147
|
|
143
|
-
describe
|
144
|
-
it
|
148
|
+
describe "#respond_to?" do
|
149
|
+
it "should return true if any chained buckets respond to the given method" do
|
145
150
|
expect(@bucket_chain.respond_to?(:foo)).to(eq(false))
|
146
151
|
expect(@chained_buckets[1]).to(receive(:respond_to?).with(:bar).and_return(true))
|
147
152
|
expect(@bucket_chain.respond_to?(:bar)).to(eq(true))
|
148
153
|
end
|
149
154
|
end
|
150
155
|
|
151
|
-
describe
|
152
|
-
it
|
156
|
+
describe "#method_missing" do
|
157
|
+
it "should try each bucket" do
|
153
158
|
expect(@chained_buckets[1]).to(receive(:buzz).and_return(true))
|
154
159
|
expect(@chained_buckets[2]).not_to(receive(:buzz))
|
155
160
|
expect(@bucket_chain.buzz).to(eq(true))
|
data/spec/bucket_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
describe AssetCloud::Bucket do
|
5
6
|
before do
|
@@ -8,19 +9,19 @@ describe AssetCloud::Bucket do
|
|
8
9
|
|
9
10
|
describe "operations not supported" do
|
10
11
|
it "#ls not supported" do
|
11
|
-
expect { @bucket.ls(
|
12
|
+
expect { @bucket.ls("foo") }.to(raise_error(NotImplementedError))
|
12
13
|
end
|
13
14
|
|
14
15
|
it "#read(key) not supported" do
|
15
|
-
expect { @bucket.read(
|
16
|
+
expect { @bucket.read("foo") }.to(raise_error(NotImplementedError))
|
16
17
|
end
|
17
18
|
|
18
19
|
it "#write(key, data) not supported" do
|
19
|
-
expect { @bucket.write(
|
20
|
+
expect { @bucket.write("foo", "bar") }.to(raise_error(NotImplementedError))
|
20
21
|
end
|
21
22
|
|
22
23
|
it "#delete(key) not supported" do
|
23
|
-
expect { @bucket.delete(
|
24
|
+
expect { @bucket.delete("foo") }.to(raise_error(NotImplementedError))
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|