asset_cloud 1.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +13 -0
- data/Rakefile +24 -0
- data/asset_cloud.gemspec +24 -0
- data/lib/asset_cloud.rb +54 -0
- data/lib/asset_cloud/asset.rb +187 -0
- data/lib/asset_cloud/asset_extension.rb +42 -0
- data/lib/asset_cloud/base.rb +247 -0
- data/lib/asset_cloud/bucket.rb +39 -0
- data/lib/asset_cloud/buckets/active_record_bucket.rb +57 -0
- data/lib/asset_cloud/buckets/blackhole_bucket.rb +23 -0
- data/lib/asset_cloud/buckets/bucket_chain.rb +84 -0
- data/lib/asset_cloud/buckets/file_system_bucket.rb +79 -0
- data/lib/asset_cloud/buckets/invalid_bucket.rb +28 -0
- data/lib/asset_cloud/buckets/memory_bucket.rb +42 -0
- data/lib/asset_cloud/buckets/versioned_memory_bucket.rb +33 -0
- data/lib/asset_cloud/callbacks.rb +63 -0
- data/lib/asset_cloud/free_key_locator.rb +28 -0
- data/lib/asset_cloud/metadata.rb +29 -0
- data/lib/asset_cloud/validations.rb +52 -0
- data/spec/active_record_bucket_spec.rb +95 -0
- data/spec/asset_extension_spec.rb +103 -0
- data/spec/asset_spec.rb +177 -0
- data/spec/base_spec.rb +114 -0
- data/spec/blackhole_bucket_spec.rb +41 -0
- data/spec/bucket_chain_spec.rb +158 -0
- data/spec/callbacks_spec.rb +125 -0
- data/spec/file_system_spec.rb +74 -0
- data/spec/files/products/key.txt +1 -0
- data/spec/files/versioned_stuff/foo +1 -0
- data/spec/find_free_key_spec.rb +39 -0
- data/spec/memory_bucket_spec.rb +52 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/validations_spec.rb +53 -0
- data/spec/versioned_memory_bucket_spec.rb +36 -0
- metadata +151 -0
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class SpecialAsset < AssetCloud::Asset
|
4
|
+
end
|
5
|
+
|
6
|
+
class BasicCloud < AssetCloud::Base
|
7
|
+
bucket :special, AssetCloud::MemoryBucket, :asset_class => SpecialAsset
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
describe BasicCloud do
|
12
|
+
directory = File.dirname(__FILE__) + '/files'
|
13
|
+
|
14
|
+
before do
|
15
|
+
@fs = BasicCloud.new(directory , 'http://assets/files' )
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise invalid bucket if none is given" do
|
19
|
+
@fs['image.jpg'].exist?.should == false
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it "should be backed by a file system bucket" do
|
24
|
+
@fs['products/key.txt'].exist?.should == true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should raise when listing non existing buckets" do
|
28
|
+
@fs.ls('products').should == [AssetCloud::Asset.new(@fs, 'products/key.txt')]
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
it "should allow you to create new assets" do
|
33
|
+
obj = @fs.build('new_file.test')
|
34
|
+
obj.should be_an_instance_of(AssetCloud::Asset)
|
35
|
+
obj.cloud.should be_an_instance_of(BasicCloud)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should raise error when using with minus relative or absolute paths" do
|
39
|
+
lambda { @fs['../test'] }.should raise_error(AssetCloud::IllegalPath)
|
40
|
+
lambda { @fs['/test'] }.should raise_error(AssetCloud::IllegalPath)
|
41
|
+
lambda { @fs['.../test'] }.should raise_error(AssetCloud::IllegalPath)
|
42
|
+
lambda { @fs['./test'] }.should raise_error(AssetCloud::IllegalPath)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should allow sensible relative filenames" do
|
46
|
+
@fs['assets/rails_logo.gif']
|
47
|
+
@fs['assets/rails-2.gif']
|
48
|
+
@fs['assets/223434.gif']
|
49
|
+
@fs['files/1.JPG']
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should compute complete urls to assets" do
|
53
|
+
@fs.url_for('products/key with spaces.txt').should == 'http://assets/files/products/key%20with%20spaces.txt'
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#find" do
|
57
|
+
it "should return the appropriate asset when one exists" do
|
58
|
+
asset = @fs.find('products/key.txt')
|
59
|
+
asset.key.should == 'products/key.txt'
|
60
|
+
asset.value.should == 'value'
|
61
|
+
end
|
62
|
+
it "should raise AssetNotFoundError when the asset doesn't exist" do
|
63
|
+
lambda { @fs.find('products/not-there.txt') }.should raise_error(AssetCloud::AssetNotFoundError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#[]" do
|
68
|
+
it "should return the appropriate asset when one exists" do
|
69
|
+
asset = @fs['products/key.txt']
|
70
|
+
asset.key.should == 'products/key.txt'
|
71
|
+
asset.value.should == 'value'
|
72
|
+
end
|
73
|
+
it "should not raise any errors when the asset doesn't exist" do
|
74
|
+
lambda { @fs['products/not-there.txt'] }.should_not raise_error
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#[]=" do
|
79
|
+
it "should write through the Asset object (and thus run any callbacks on the asset)" do
|
80
|
+
special_asset = double(:special_asset)
|
81
|
+
special_asset.should_receive(:value=).with('fancy fancy!')
|
82
|
+
special_asset.should_receive(:store)
|
83
|
+
SpecialAsset.should_receive(:at).and_return(special_asset)
|
84
|
+
@fs['special/fancy.txt'] = 'fancy fancy!'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#bucket" do
|
89
|
+
it "should allow specifying a class to use for assets in this bucket" do
|
90
|
+
@fs['assets/rails_logo.gif'].should be_instance_of(AssetCloud::Asset)
|
91
|
+
@fs['special/fancy.txt'].should be_instance_of(SpecialAsset)
|
92
|
+
|
93
|
+
@fs.build('assets/foo').should be_instance_of(AssetCloud::Asset)
|
94
|
+
@fs.build('special/foo').should be_instance_of(SpecialAsset)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "MATCH_BUCKET" do
|
99
|
+
it "should match following stuff " do
|
100
|
+
|
101
|
+
'products/key.txt' =~ AssetCloud::Base::MATCH_BUCKET
|
102
|
+
$1.should == 'products'
|
103
|
+
|
104
|
+
'products/subpath/key.txt' =~ AssetCloud::Base::MATCH_BUCKET
|
105
|
+
$1.should == 'products'
|
106
|
+
|
107
|
+
'key.txt' =~ AssetCloud::Base::MATCH_BUCKET
|
108
|
+
$1.should == nil
|
109
|
+
|
110
|
+
'products' =~ AssetCloud::Base::MATCH_BUCKET
|
111
|
+
$1.should == 'products'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BlackholeCloud < AssetCloud::Base
|
4
|
+
bucket AssetCloud::BlackholeBucket
|
5
|
+
end
|
6
|
+
|
7
|
+
describe BlackholeCloud do
|
8
|
+
directory = File.dirname(__FILE__) + '/files'
|
9
|
+
|
10
|
+
before do
|
11
|
+
@fs = BlackholeCloud.new(directory , 'http://assets/files' )
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow access to files using the [] operator" do
|
15
|
+
@fs['tmp/image.jpg']
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return nil for non existent files" do
|
19
|
+
@fs['tmp/image.jpg'].exist?.should == false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should still return nil, even if you wrote something there" do
|
23
|
+
@fs['tmp/image.jpg'] = 'test'
|
24
|
+
@fs['tmp/image.jpg'].exist?.should == false
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "when using a sub path" do
|
28
|
+
it "should allow access to files using the [] operator" do
|
29
|
+
@fs['tmp/image.jpg']
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return nil for non existent files" do
|
33
|
+
@fs['tmp/image.jpg'].exist?.should == false
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should still return nil, even if you wrote something there" do
|
37
|
+
@fs['tmp/image.jpg'] = 'test'
|
38
|
+
@fs['tmp/image.jpg'].exist?.should == false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ChainedCloud < AssetCloud::Base
|
4
|
+
bucket :stuff, AssetCloud::BucketChain.chain( AssetCloud::MemoryBucket,
|
5
|
+
AssetCloud::MemoryBucket,
|
6
|
+
AssetCloud::FileSystemBucket )
|
7
|
+
|
8
|
+
bucket :versioned_stuff, AssetCloud::BucketChain.chain( AssetCloud::FileSystemBucket,
|
9
|
+
AssetCloud::VersionedMemoryBucket,
|
10
|
+
AssetCloud::MemoryBucket )
|
11
|
+
end
|
12
|
+
|
13
|
+
describe AssetCloud::BucketChain do
|
14
|
+
directory = File.dirname(__FILE__) + '/files'
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
@cloud = ChainedCloud.new(directory , 'http://assets/files' )
|
18
|
+
@bucket_chain = @cloud.buckets[:stuff]
|
19
|
+
@chained_buckets = @bucket_chain.chained_buckets
|
20
|
+
@chained_buckets.each {|b| b.ls('stuff').each {|asset| asset.delete}}
|
21
|
+
|
22
|
+
@versioned_stuff = @cloud.buckets[:versioned_stuff]
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".chain" do
|
26
|
+
it 'should take multiple Bucket classes and return a new Bucket class' do
|
27
|
+
@bucket_chain.should be_a_kind_of(AssetCloud::BucketChain)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#write" do
|
32
|
+
it 'should write to each sub-bucket when everything is kosher and return the result of the first write' do
|
33
|
+
@chained_buckets.each do |bucket|
|
34
|
+
bucket.should_receive(:write).with('stuff/foo', 'successful creation').and_return('successful creation')
|
35
|
+
end
|
36
|
+
|
37
|
+
@bucket_chain.write('stuff/foo', 'successful creation').should == 'successful creation'
|
38
|
+
end
|
39
|
+
it 'should roll back creation-writes and re-raise an error when a bucket raises one' do
|
40
|
+
@chained_buckets.last.should_receive(:write).with('stuff/foo', 'unsuccessful creation').and_raise('hell')
|
41
|
+
@chained_buckets[0..-2].each do |bucket|
|
42
|
+
bucket.should_receive(:write).with('stuff/foo', 'unsuccessful creation').and_return(true)
|
43
|
+
bucket.should_receive(:delete).with('stuff/foo').and_return(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
lambda { @bucket_chain.write('stuff/foo', 'unsuccessful creation') }.should raise_error(RuntimeError)
|
47
|
+
end
|
48
|
+
it 'should roll back update-writes and re-raise an error when a bucket raises one' do
|
49
|
+
@bucket_chain.write('stuff/foo', "original value")
|
50
|
+
|
51
|
+
@chained_buckets.last.should_receive(:write).with('stuff/foo', 'new value').and_raise('hell')
|
52
|
+
|
53
|
+
lambda { @bucket_chain.write('stuff/foo', 'new value') }.should raise_error(RuntimeError)
|
54
|
+
@chained_buckets.each do |bucket|
|
55
|
+
bucket.read('stuff/foo').should == 'original value'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#delete" do
|
61
|
+
it 'should delete from each sub-bucket when everything is kosher' do
|
62
|
+
@bucket_chain.write('stuff/foo', "successful deletion comin' up")
|
63
|
+
|
64
|
+
@chained_buckets.each do |bucket|
|
65
|
+
bucket.should_receive(:delete).with('stuff/foo').and_return(true)
|
66
|
+
end
|
67
|
+
|
68
|
+
@bucket_chain.delete('stuff/foo')
|
69
|
+
end
|
70
|
+
it 'should roll back deletions and re-raise an error when a bucket raises one' do
|
71
|
+
@bucket_chain.write('stuff/foo', "this deletion will fail")
|
72
|
+
|
73
|
+
@chained_buckets.last.should_receive(:delete).with('stuff/foo').and_raise('hell')
|
74
|
+
@chained_buckets[0..-2].each do |bucket|
|
75
|
+
bucket.should_receive(:delete).with('stuff/foo').and_return(true)
|
76
|
+
bucket.should_receive(:write).with('stuff/foo', 'this deletion will fail').and_return(true)
|
77
|
+
end
|
78
|
+
|
79
|
+
lambda { @bucket_chain.delete('stuff/foo') }.should raise_error(RuntimeError)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#read" do
|
84
|
+
it 'should read from only the first available sub-bucket' do
|
85
|
+
@chained_buckets[0].should_receive(:read).with('stuff/foo').and_raise(NotImplementedError)
|
86
|
+
@chained_buckets[0].should_receive(:ls).with(nil).and_raise(NoMethodError)
|
87
|
+
@chained_buckets[0].should_receive(:stat).and_return(:metadata)
|
88
|
+
|
89
|
+
@chained_buckets[1].should_receive(:read).with('stuff/foo').and_return('bar')
|
90
|
+
@chained_buckets[1].should_receive(:ls).with(nil).and_return(:some_assets)
|
91
|
+
@chained_buckets[1].should_not_receive(:stat)
|
92
|
+
|
93
|
+
@chained_buckets[2..-1].each do |bucket|
|
94
|
+
bucket.should_not_receive(:read)
|
95
|
+
bucket.should_not_receive(:ls)
|
96
|
+
bucket.should_not_receive(:stat)
|
97
|
+
end
|
98
|
+
|
99
|
+
@bucket_chain.read('stuff/foo').should == 'bar'
|
100
|
+
@bucket_chain.ls.should == :some_assets
|
101
|
+
@bucket_chain.stat.should == :metadata
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
describe "#read_version" do
|
107
|
+
it 'should read from only the first available sub-bucket' do
|
108
|
+
buckets = @versioned_stuff.chained_buckets
|
109
|
+
|
110
|
+
buckets[1].should_receive(:read_version).with('stuff/foo',3).and_return('bar')
|
111
|
+
buckets.last.should_not_receive(:read_version)
|
112
|
+
|
113
|
+
@versioned_stuff.read_version('stuff/foo', 3).should == 'bar'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#versions" do
|
118
|
+
it 'should read from only the first available sub-bucket' do
|
119
|
+
buckets = @versioned_stuff.chained_buckets
|
120
|
+
|
121
|
+
buckets[1].should_receive(:versions).with('versioned_stuff/foo').and_return([1,2,3])
|
122
|
+
buckets.last.should_not_receive(:versions)
|
123
|
+
|
124
|
+
@versioned_stuff.versions('versioned_stuff/foo').should == [1,2,3]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "with versioned buckets" do
|
129
|
+
it 'should store and retrieve versions seamlessly' do
|
130
|
+
%w{one two three}.each do |content|
|
131
|
+
@cloud['versioned_stuff/foo'] = content
|
132
|
+
end
|
133
|
+
asset = @cloud['versioned_stuff/foo']
|
134
|
+
asset.value.should == 'three'
|
135
|
+
asset.rollback(1).value.should == 'one'
|
136
|
+
asset.versions.should == [1,2,3]
|
137
|
+
asset.value = 'four'
|
138
|
+
asset.store
|
139
|
+
asset.versions.should == [1,2,3,4]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#respond_to?' do
|
144
|
+
it 'should return true if any chained buckets respond to the given method' do
|
145
|
+
@bucket_chain.respond_to?(:foo).should == false
|
146
|
+
@chained_buckets[1].should_receive(:respond_to?).with(:bar).and_return(true)
|
147
|
+
@bucket_chain.respond_to?(:bar).should == true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#method_missing' do
|
152
|
+
it 'should try each bucket' do
|
153
|
+
@chained_buckets[1].should_receive(:buzz).and_return(true)
|
154
|
+
@chained_buckets[2].should_not_receive(:buzz)
|
155
|
+
@bucket_chain.buzz.should == true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class CallbackAsset < AssetCloud::Asset
|
4
|
+
before_store :callback_before_store
|
5
|
+
after_delete :callback_after_delete
|
6
|
+
before_validate :make_value_valid
|
7
|
+
after_validate :add_spice
|
8
|
+
validate :valid_value
|
9
|
+
|
10
|
+
private
|
11
|
+
def make_value_valid
|
12
|
+
self.value = 'valid'
|
13
|
+
end
|
14
|
+
def add_spice
|
15
|
+
self.value += ' spice'
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_value
|
19
|
+
add_error 'value is not "valid"' unless value == 'valid'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class BasicCloud < AssetCloud::Base
|
24
|
+
bucket :callback_assets, AssetCloud::MemoryBucket, :asset_class => CallbackAsset
|
25
|
+
end
|
26
|
+
|
27
|
+
class CallbackCloud < AssetCloud::Base
|
28
|
+
bucket :tmp, AssetCloud::MemoryBucket
|
29
|
+
|
30
|
+
after_delete :callback_after_delete
|
31
|
+
before_delete :callback_before_delete
|
32
|
+
|
33
|
+
after_write :callback_after_write
|
34
|
+
before_write :callback_before_write
|
35
|
+
end
|
36
|
+
|
37
|
+
class MethodRecordingCloud < AssetCloud::Base
|
38
|
+
attr_accessor :run_callbacks
|
39
|
+
|
40
|
+
bucket :tmp, AssetCloud::MemoryBucket
|
41
|
+
|
42
|
+
before_write :callback_before_write
|
43
|
+
after_write :callback_before_write
|
44
|
+
|
45
|
+
|
46
|
+
def method_missing(method, *args)
|
47
|
+
@run_callbacks << method.to_sym
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe CallbackCloud do
|
52
|
+
before { @fs = CallbackCloud.new(File.dirname(__FILE__) + '/files', 'http://assets/') }
|
53
|
+
|
54
|
+
it "should invoke callbacks after store" do
|
55
|
+
|
56
|
+
@fs.should_receive(:callback_before_write).with('tmp/file.txt', 'text').and_return(true)
|
57
|
+
@fs.should_receive(:callback_after_write).with('tmp/file.txt', 'text').and_return(true)
|
58
|
+
|
59
|
+
|
60
|
+
@fs.write 'tmp/file.txt', 'text'
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should invoke callbacks after delete" do
|
65
|
+
|
66
|
+
@fs.should_receive(:callback_before_delete).with('tmp/file.txt').and_return(true)
|
67
|
+
@fs.should_receive(:callback_after_delete).with('tmp/file.txt').and_return(true)
|
68
|
+
|
69
|
+
|
70
|
+
@fs.delete 'tmp/file.txt'
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should invoke callbacks even when constructing a new asset" do
|
74
|
+
@fs.should_receive(:callback_before_write).with('tmp/file.txt', 'hello').and_return(true)
|
75
|
+
@fs.should_receive(:callback_after_write).with('tmp/file.txt', 'hello').and_return(true)
|
76
|
+
|
77
|
+
|
78
|
+
asset = @fs.build('tmp/file.txt')
|
79
|
+
asset.value = 'hello'
|
80
|
+
asset.store
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe MethodRecordingCloud do
|
87
|
+
before do
|
88
|
+
@fs = MethodRecordingCloud.new(File.dirname(__FILE__) + '/files', 'http://assets/')
|
89
|
+
@fs.run_callbacks = []
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should record event when invoked' do
|
93
|
+
@fs.write('tmp/file.txt', 'random data')
|
94
|
+
@fs.run_callbacks.should == [:callback_before_write, :callback_before_write]
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should record event when assignment operator is used' do
|
98
|
+
@fs['tmp/file.txt'] = 'random data'
|
99
|
+
@fs.run_callbacks.should == [:callback_before_write, :callback_before_write]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe CallbackAsset do
|
104
|
+
before(:each) do
|
105
|
+
@fs = BasicCloud.new(File.dirname(__FILE__) + '/files', 'http://assets/')
|
106
|
+
@fs.write('callback_assets/foo', 'bar')
|
107
|
+
@asset = @fs.asset_at('callback_assets/foo')
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should run before_validate, then validate, then after validate, then before_store, then store" do
|
111
|
+
@asset.should_receive(:callback_before_store).and_return(true)
|
112
|
+
@asset.should_not_receive(:callback_after_delete)
|
113
|
+
|
114
|
+
@asset.value = 'foo'
|
115
|
+
@asset.store.should == true
|
116
|
+
@asset.value.should == 'valid spice'
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should run its after_delete callback after delete is called" do
|
120
|
+
@asset.should_not_receive(:callback_before_store)
|
121
|
+
@asset.should_receive(:callback_after_delete).and_return(true)
|
122
|
+
|
123
|
+
@asset.delete
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class FileSystemCloud < AssetCloud::Base
|
5
|
+
bucket AssetCloud::InvalidBucket
|
6
|
+
bucket :products, AssetCloud::FileSystemBucket
|
7
|
+
bucket :tmp, AssetCloud::FileSystemBucket
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
describe FileSystemCloud do
|
12
|
+
directory = File.dirname(__FILE__) + '/files'
|
13
|
+
|
14
|
+
before do
|
15
|
+
@fs = FileSystemCloud.new(directory , 'http://assets/files' )
|
16
|
+
FileUtils.mkdir_p(directory + '/tmp')
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
FileUtils.rm_rf(directory + '/tmp')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should use invalid bucket for random directories" do
|
24
|
+
@fs.bucket_for('does-not-exist/file.txt').should be_an_instance_of(AssetCloud::InvalidBucket)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should use filesystem bucekt for products/ and tmp/ directories" do
|
28
|
+
@fs.bucket_for('products/file.txt').should be_an_instance_of(AssetCloud::FileSystemBucket)
|
29
|
+
@fs.bucket_for('tmp/file.txt').should be_an_instance_of(AssetCloud::FileSystemBucket)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return Asset for existing files" do
|
33
|
+
@fs['products/key.txt'].exist?.should == true
|
34
|
+
@fs['products/key.txt'].should be_an_instance_of(AssetCloud::Asset)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should be able to test if a file exists or not" do
|
38
|
+
@fs.stat('products/key.txt').exist?.should == true
|
39
|
+
@fs.stat('products/key2.txt').exist?.should == false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be able to list files" do
|
43
|
+
@fs.ls('products').collect(&:key).should == ['products/key.txt']
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'when modifying file system' do
|
47
|
+
|
48
|
+
it "should call write after storing an asset" do
|
49
|
+
@fs.buckets[:tmp].should_receive(:write).with('tmp/new_file.test', 'hello world').and_return(true)
|
50
|
+
|
51
|
+
@fs.build('tmp/new_file.test', 'hello world').store
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be able to create new files" do
|
55
|
+
@fs.build('tmp/new_file.test', 'hello world').store
|
56
|
+
|
57
|
+
@fs.stat('tmp/new_file.test').exist.should == true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be able to create new files with simple assignment" do
|
61
|
+
@fs['tmp/new_file.test'] = 'hello world'
|
62
|
+
|
63
|
+
@fs.stat('tmp/new_file.test').exist.should == true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should create directories as needed" do
|
67
|
+
@fs.build('tmp/new_file.test', 'hello world').store
|
68
|
+
|
69
|
+
@fs['tmp/new_file.test'].exist?.should == true
|
70
|
+
@fs['tmp/new_file.test'].value.should == 'hello world'
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|