asset_cloud 2.7.1 → 2.7.3
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 +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +21 -7
- data/.github/workflows/cla.yml +22 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +0 -1
- data/.ruby-version +1 -0
- data/Gemfile +5 -3
- data/Gemfile.lock +180 -0
- data/History.md +9 -0
- data/README.rdoc +1 -3
- data/Rakefile +18 -16
- data/asset_cloud.gemspec +19 -18
- data/dev.yml +1 -2
- 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 +24 -16
- 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 +24 -22
- 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 +65 -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 +13 -36
- data/.github/probots.yml +0 -2
- data/.rubocop_todo.yml +0 -326
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "aws-sdk-s3"
|
2
4
|
|
3
5
|
module AssetCloud
|
4
6
|
class S3Bucket < Bucket
|
@@ -18,7 +20,7 @@ module AssetCloud
|
|
18
20
|
options[:range] = http_byte_range(options[:range]) if options[:range]
|
19
21
|
|
20
22
|
bucket = cloud.s3_bucket(key)
|
21
|
-
if encryption_key = options.delete(:encryption_key)
|
23
|
+
if (encryption_key = options.delete(:encryption_key))
|
22
24
|
bucket = encrypted_bucket(bucket, encryption_key)
|
23
25
|
end
|
24
26
|
|
@@ -33,7 +35,7 @@ module AssetCloud
|
|
33
35
|
options = options.dup
|
34
36
|
|
35
37
|
bucket = cloud.s3_bucket(key)
|
36
|
-
if encryption_key = options.delete(:encryption_key)
|
38
|
+
if (encryption_key = options.delete(:encryption_key))
|
37
39
|
bucket = encrypted_bucket(bucket, encryption_key)
|
38
40
|
end
|
39
41
|
|
@@ -63,7 +65,7 @@ module AssetCloud
|
|
63
65
|
client: Aws::S3::Encryption::Client.new(
|
64
66
|
client: source_bucket.client,
|
65
67
|
encryption_key: key,
|
66
|
-
)
|
68
|
+
),
|
67
69
|
).bucket(source_bucket.name)
|
68
70
|
end
|
69
71
|
|
@@ -73,21 +75,22 @@ module AssetCloud
|
|
73
75
|
|
74
76
|
def absolute_key(key = nil)
|
75
77
|
if key.to_s.starts_with?(path_prefix)
|
76
|
-
|
78
|
+
key
|
77
79
|
else
|
78
80
|
args = [path_prefix]
|
79
81
|
args << key.to_s if key
|
80
|
-
args.join(
|
82
|
+
args.join("/")
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
86
|
def relative_key(key)
|
85
|
-
key =~
|
87
|
+
key =~ %r{^#{path_prefix}/(.+)} ? Regexp.last_match(1) : key
|
86
88
|
end
|
87
89
|
|
88
90
|
def http_byte_range(range)
|
89
91
|
# follows https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
|
90
|
-
return "bytes=#{[range.begin, range.max].join(
|
92
|
+
return "bytes=#{[range.begin, range.max].join("-")}" if range.is_a?(Range)
|
93
|
+
|
91
94
|
range
|
92
95
|
end
|
93
96
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class VersionedMemoryBucket < MemoryBucket
|
3
|
-
|
4
5
|
def read(key)
|
5
|
-
raise AssetCloud::AssetNotFoundError, key unless @memory.
|
6
|
+
raise AssetCloud::AssetNotFoundError, key unless @memory.key?(key)
|
7
|
+
|
6
8
|
read_version(key, latest_version(key))
|
7
9
|
end
|
8
10
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
module Callbacks
|
3
5
|
extend ActiveSupport::Concern
|
@@ -33,13 +35,13 @@ module AssetCloud
|
|
33
35
|
end
|
34
36
|
|
35
37
|
define_singleton_method(before) do |*callbacks, &block|
|
36
|
-
callbacks << block
|
38
|
+
callbacks << block unless block.nil?
|
37
39
|
callbacks = (_callbacks[before] || []) + callbacks
|
38
40
|
self._callbacks = _callbacks.merge(before => callbacks).freeze
|
39
41
|
end
|
40
42
|
|
41
43
|
define_singleton_method(after) do |*callbacks, &block|
|
42
|
-
callbacks << block
|
44
|
+
callbacks << block unless block.nil?
|
43
45
|
callbacks = (_callbacks[after] || []) + callbacks
|
44
46
|
self._callbacks = _callbacks.merge(after => callbacks).freeze
|
45
47
|
end
|
@@ -50,7 +52,7 @@ module AssetCloud
|
|
50
52
|
def extension_module
|
51
53
|
@extension_module ||= begin
|
52
54
|
mod = Module.new
|
53
|
-
|
55
|
+
const_set(:AssetCloudCallbacks, mod)
|
54
56
|
prepend(mod)
|
55
57
|
mod
|
56
58
|
end
|
@@ -59,24 +61,30 @@ module AssetCloud
|
|
59
61
|
|
60
62
|
def execute_callbacks(symbol, args)
|
61
63
|
callbacks_for(symbol).each do |callback|
|
62
|
-
|
63
|
-
result = case callback
|
64
|
-
when Symbol
|
65
|
-
send(callback, *args)
|
66
|
-
when Proc, Method
|
67
|
-
callback.call(self, *args)
|
68
|
-
else
|
69
|
-
if callback.respond_to?(symbol)
|
70
|
-
callback.send(symbol, self, *args)
|
71
|
-
else
|
72
|
-
raise StandardError, "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method."
|
73
|
-
end
|
74
|
-
end
|
64
|
+
result = execute_callback(symbol, callback, args)
|
75
65
|
return false if result == false
|
76
66
|
end
|
77
67
|
true
|
78
68
|
end
|
79
69
|
|
70
|
+
def execute_callback(symbol, callback, args)
|
71
|
+
case callback
|
72
|
+
when Symbol
|
73
|
+
send(callback, *args)
|
74
|
+
when Proc, Method
|
75
|
+
callback.call(self, *args)
|
76
|
+
else
|
77
|
+
if callback.respond_to?(symbol)
|
78
|
+
callback.send(symbol, self, *args)
|
79
|
+
else
|
80
|
+
raise StandardError,
|
81
|
+
"Callbacks must be a symbol denoting the method to call, " \
|
82
|
+
"a string to be evaluated, a block to be invoked, " \
|
83
|
+
"or an object responding to the callback method."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
80
88
|
def callbacks_for(symbol)
|
81
89
|
self.class._callbacks[symbol] || []
|
82
90
|
end
|
@@ -1,26 +1,26 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "securerandom"
|
4
4
|
|
5
|
+
module AssetCloud
|
5
6
|
module FreeKeyLocator
|
6
|
-
|
7
7
|
def find_free_key_like(key, options = {})
|
8
8
|
# Check weather the suggested key name is free. If so we
|
9
9
|
# simply return it.
|
10
10
|
|
11
|
-
if !exist?(key)
|
11
|
+
if !options[:force_uuid] && !exist?(key)
|
12
12
|
key
|
13
13
|
else
|
14
14
|
ext = File.extname(key)
|
15
15
|
dirname = File.dirname(key)
|
16
|
-
base = dirname ==
|
16
|
+
base = dirname == "." ? File.basename(key, ext) : File.join(File.dirname(key), File.basename(key, ext))
|
17
17
|
base = base.gsub(/_[\h]{8}-[\h]{4}-4[\h]{3}-[\h]{4}-[\h]{12}/, "")
|
18
18
|
|
19
19
|
# Attach UUID to avoid name collision
|
20
20
|
key = "#{base}_#{SecureRandom.uuid}#{ext}"
|
21
21
|
return key unless exist?(key)
|
22
22
|
|
23
|
-
raise StandardError,
|
23
|
+
raise StandardError, "Filesystem out of free filenames"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
data/lib/asset_cloud/metadata.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class Metadata
|
3
5
|
attr_accessor :exist, :size, :created_at, :updated_at, :value_hash, :checksum
|
4
6
|
|
5
7
|
def new?
|
6
|
-
!
|
8
|
+
!exist
|
7
9
|
end
|
8
10
|
|
9
11
|
def exist?
|
10
|
-
|
12
|
+
exist
|
11
13
|
end
|
12
14
|
|
13
15
|
# rubocop:disable Metrics/ParameterLists
|
@@ -21,12 +23,14 @@ module AssetCloud
|
|
21
23
|
end
|
22
24
|
# rubocop:enable Metrics/ParameterLists
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
class << self
|
27
|
+
def existing
|
28
|
+
new(true)
|
29
|
+
end
|
27
30
|
|
28
|
-
|
29
|
-
|
31
|
+
def non_existing
|
32
|
+
new(false)
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
def inspect
|
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
module Validations
|
3
|
-
|
4
|
-
base
|
5
|
-
|
6
|
-
|
5
|
+
class << self
|
6
|
+
def included(base)
|
7
|
+
base.send(:alias_method, :store_without_validation, :store)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
base.prepend(PrependedMethods)
|
10
|
+
end
|
7
11
|
end
|
8
12
|
|
9
13
|
module PrependedMethods
|
@@ -15,7 +19,7 @@ module AssetCloud
|
|
15
19
|
|
16
20
|
module ClassMethods
|
17
21
|
def validate(*extra_validations, &block)
|
18
|
-
validations =
|
22
|
+
validations = _callbacks[:validate] || []
|
19
23
|
validations += extra_validations
|
20
24
|
validations << block if block_given?
|
21
25
|
|
data/lib/asset_cloud.rb
CHANGED
@@ -1,36 +1,38 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "addressable"
|
4
|
+
require "active_support"
|
3
5
|
|
4
6
|
# Core
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
7
|
+
require "asset_cloud/asset"
|
8
|
+
require "asset_cloud/metadata"
|
9
|
+
require "asset_cloud/bucket"
|
10
|
+
require "asset_cloud/buckets/active_record_bucket"
|
11
|
+
require "asset_cloud/buckets/blackhole_bucket"
|
12
|
+
require "asset_cloud/buckets/bucket_chain"
|
13
|
+
require "asset_cloud/buckets/file_system_bucket"
|
14
|
+
require "asset_cloud/buckets/invalid_bucket"
|
15
|
+
require "asset_cloud/buckets/memory_bucket"
|
16
|
+
require "asset_cloud/buckets/versioned_memory_bucket"
|
17
|
+
require "asset_cloud/base"
|
16
18
|
|
17
19
|
# S3
|
18
|
-
require
|
20
|
+
require "asset_cloud/buckets/s3_bucket"
|
19
21
|
|
20
22
|
# GCS
|
21
|
-
require
|
23
|
+
require "asset_cloud/buckets/gcs_bucket"
|
22
24
|
|
23
25
|
# Extensions
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
26
|
+
require "asset_cloud/free_key_locator"
|
27
|
+
require "asset_cloud/callbacks"
|
28
|
+
require "asset_cloud/validations"
|
27
29
|
|
28
|
-
require
|
30
|
+
require "asset_cloud/asset_extension"
|
29
31
|
|
30
32
|
AssetCloud::Base.class_eval do
|
31
33
|
include AssetCloud::FreeKeyLocator
|
32
34
|
include AssetCloud::Callbacks
|
33
|
-
callback_methods :
|
35
|
+
callback_methods :write, :delete
|
34
36
|
end
|
35
37
|
|
36
38
|
AssetCloud::Asset.class_eval do
|
@@ -56,9 +58,9 @@ AssetCloud::Asset.class_eval do
|
|
56
58
|
|
57
59
|
def valid_key
|
58
60
|
if key.blank?
|
59
|
-
add_error
|
61
|
+
add_error("key cannot be empty")
|
60
62
|
elsif !valid_key_path?(key)
|
61
|
-
add_error
|
63
|
+
add_error("#{key.inspect} contains illegal characters")
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
MockRecords = Object.new
|
5
6
|
|
6
7
|
class MockActiveRecordBucket < AssetCloud::ActiveRecordBucket
|
7
|
-
self.key_attribute =
|
8
|
-
self.value_attribute =
|
8
|
+
self.key_attribute = "name"
|
9
|
+
self.value_attribute = "body"
|
9
10
|
|
10
11
|
protected
|
11
12
|
|
@@ -19,24 +20,24 @@ class RecordCloud < AssetCloud::Base
|
|
19
20
|
end
|
20
21
|
|
21
22
|
describe AssetCloud::ActiveRecordBucket do
|
22
|
-
directory = File.dirname(__FILE__) +
|
23
|
+
directory = File.dirname(__FILE__) + "/files"
|
23
24
|
|
24
25
|
before do
|
25
|
-
@cloud = RecordCloud.new(directory,
|
26
|
+
@cloud = RecordCloud.new(directory, "http://assets/files")
|
26
27
|
@bucket = @cloud.buckets[:stuff]
|
27
28
|
end
|
28
29
|
|
29
|
-
describe
|
30
|
+
describe "#ls" do
|
30
31
|
before do
|
31
32
|
expect(MockRecords).to(receive(:connection).and_return(@mock_connection = double("connection")))
|
32
|
-
expect(@mock_connection).to(receive(:quote_column_name).with(
|
33
|
-
expect(@mock_record = double("record")).to(receive(:name).and_return(
|
33
|
+
expect(@mock_connection).to(receive(:quote_column_name).with("name").and_return("`name`"))
|
34
|
+
expect(@mock_record = double("record")).to(receive(:name).and_return("stuff/a1"))
|
34
35
|
end
|
35
36
|
|
36
37
|
it "should return a list of assets which start with the given prefix" do
|
37
38
|
expect(MockRecords).to(receive(:all).with(conditions: ["`name` LIKE ?", "stuff/a%"]).and_return([@mock_record]))
|
38
39
|
|
39
|
-
expect(@bucket.ls(
|
40
|
+
expect(@bucket.ls("stuff/a").size).to(eq(1))
|
40
41
|
end
|
41
42
|
|
42
43
|
it "should return a list of all assets when a prefix is not given" do
|
@@ -46,47 +47,47 @@ describe AssetCloud::ActiveRecordBucket do
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
describe
|
50
|
+
describe "#read" do
|
50
51
|
it "should return the value of a key when it exists" do
|
51
|
-
expect(@mock_record = double("record")).to(receive(:body).and_return(
|
52
|
-
expect(MockRecords).to(receive(:first).with(conditions: {
|
52
|
+
expect(@mock_record = double("record")).to(receive(:body).and_return("foo"))
|
53
|
+
expect(MockRecords).to(receive(:first).with(conditions: { "name" => "stuff/a1" }).and_return(@mock_record))
|
53
54
|
|
54
|
-
@bucket.read(
|
55
|
+
@bucket.read("stuff/a1")
|
55
56
|
end
|
56
57
|
it "should raise AssetNotFoundError when nothing is there" do
|
57
|
-
expect(MockRecords).to(receive(:first).with(conditions: {
|
58
|
+
expect(MockRecords).to(receive(:first).with(conditions: { "name" => "stuff/a1" }).and_return(nil))
|
58
59
|
|
59
|
-
expect { @bucket.read(
|
60
|
+
expect { @bucket.read("stuff/a1") }.to(raise_error(AssetCloud::AssetNotFoundError))
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
63
|
-
describe
|
64
|
+
describe "#write" do
|
64
65
|
it "should write to the DB" do
|
65
|
-
expect(@mock_record = double("record")).to(receive(:body=).with(
|
66
|
+
expect(@mock_record = double("record")).to(receive(:body=).with("foo").and_return("foo"))
|
66
67
|
expect(@mock_record).to(receive(:save!).and_return(true))
|
67
|
-
expect(MockRecords).to(receive(:find_or_initialize_by_name).with(
|
68
|
+
expect(MockRecords).to(receive(:find_or_initialize_by_name).with("stuff/a1").and_return(@mock_record))
|
68
69
|
|
69
|
-
@bucket.write(
|
70
|
+
@bucket.write("stuff/a1", "foo")
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
describe
|
74
|
+
describe "#delete" do
|
74
75
|
it "should destroy records" do
|
75
76
|
expect(@mock_record = double("record")).to(receive(:destroy).and_return(true))
|
76
|
-
expect(MockRecords).to(receive(:first).with(conditions: {
|
77
|
+
expect(MockRecords).to(receive(:first).with(conditions: { "name" => "stuff/a1" }).and_return(@mock_record))
|
77
78
|
|
78
|
-
@bucket.delete(
|
79
|
+
@bucket.delete("stuff/a1")
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
|
-
describe
|
83
|
+
describe "#stat" do
|
83
84
|
it "should return appropriate metadata" do
|
84
85
|
expect(@mock_record = double("record")).to(receive(:created_at).and_return(1982))
|
85
86
|
expect(@mock_record).to(receive(:updated_at).and_return(2002))
|
86
|
-
expect(@mock_record).to(receive(:body).and_return(
|
87
|
-
expect(MockRecords).to(receive(:first).with(conditions: {
|
87
|
+
expect(@mock_record).to(receive(:body).and_return("foo"))
|
88
|
+
expect(MockRecords).to(receive(:first).with(conditions: { "name" => "stuff/a1" }).and_return(@mock_record))
|
88
89
|
|
89
|
-
metadata = @bucket.stat(
|
90
|
+
metadata = @bucket.stat("stuff/a1")
|
90
91
|
expect(metadata.created_at).to(eq(1982))
|
91
92
|
expect(metadata.updated_at).to(eq(2002))
|
92
93
|
expect(metadata.size).to(eq(3))
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
class NoCatsAsset < AssetCloud::Asset
|
5
6
|
validate :no_cats
|
@@ -8,7 +9,7 @@ class NoCatsAsset < AssetCloud::Asset
|
|
8
9
|
private
|
9
10
|
|
10
11
|
def no_cats
|
11
|
-
add_error(
|
12
|
+
add_error("no cats allowed!") if value =~ /cat/i
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
@@ -53,33 +54,33 @@ describe "AssetExtension" do
|
|
53
54
|
include AssetCloud
|
54
55
|
|
55
56
|
before do
|
56
|
-
@cloud = CatsAndDogsCloud.new(File.dirname(__FILE__) +
|
57
|
+
@cloud = CatsAndDogsCloud.new(File.dirname(__FILE__) + "/files", "http://assets/")
|
57
58
|
end
|
58
59
|
|
59
60
|
describe "applicability" do
|
60
61
|
it "should work" do
|
61
|
-
asset = @cloud[
|
62
|
+
asset = @cloud["cat_pen/cats.xml"]
|
62
63
|
expect(XmlAssetExtension.applies_to_asset?(asset)).to(eq(true))
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
66
67
|
describe "validations" do
|
67
68
|
it "should be added to assets in the right bucket with the right extension" do
|
68
|
-
asset = @cloud[
|
69
|
-
asset.value =
|
69
|
+
asset = @cloud["cat_pen/cats.css"]
|
70
|
+
asset.value = "foo"
|
70
71
|
expect(asset.store).to(eq(false))
|
71
72
|
expect(asset.errors).to(eq(["not enough curly brackets!"]))
|
72
73
|
end
|
73
74
|
|
74
75
|
it "should not squash existing validations on the asset" do
|
75
|
-
asset = @cloud[
|
76
|
-
asset.value =
|
76
|
+
asset = @cloud["dog_pound/cats.xml"]
|
77
|
+
asset.value = "cats!"
|
77
78
|
expect(asset.store).to(eq(false))
|
78
|
-
expect(asset.errors).to(eq([
|
79
|
+
expect(asset.errors).to(eq(["no cats allowed!", "not enough angle brackets!"]))
|
79
80
|
end
|
80
81
|
|
81
82
|
it "should not apply to non-matching assets or those in exempted buckets" do
|
82
|
-
asset = @cloud[
|
83
|
+
asset = @cloud["cat_pen/cats.xml"]
|
83
84
|
asset.value = "xml"
|
84
85
|
expect(asset.store).to(eq(true))
|
85
86
|
end
|
@@ -87,20 +88,20 @@ describe "AssetExtension" do
|
|
87
88
|
|
88
89
|
describe "callbacks" do
|
89
90
|
it "should run alongside the asset's callbacks" do
|
90
|
-
asset = @cloud[
|
91
|
+
asset = @cloud["dog_pound/dogs.xml"]
|
91
92
|
expect(asset).to(receive(:asset_callback))
|
92
93
|
expect(asset.extensions.first).to(receive(:xml_callback))
|
93
|
-
asset.value =
|
94
|
+
asset.value = "<dogs/>"
|
94
95
|
expect(asset.store).to(eq(true))
|
95
96
|
end
|
96
97
|
end
|
97
98
|
|
98
99
|
describe "#method_missing" do
|
99
100
|
it "should try to run method on extensions" do
|
100
|
-
asset = @cloud[
|
101
|
-
asset.value =
|
101
|
+
asset = @cloud["dog_pound/dogs.xml"]
|
102
|
+
asset.value = "dogs"
|
102
103
|
asset.turn_into_xml
|
103
|
-
expect(asset.value).to(eq(
|
104
|
+
expect(asset.value).to(eq("<xml>dogs</xml>"))
|
104
105
|
end
|
105
106
|
|
106
107
|
it "does not swallow NotImplementedError" do
|
@@ -108,7 +109,7 @@ describe "AssetExtension" do
|
|
108
109
|
raise NotImplementedError
|
109
110
|
end
|
110
111
|
|
111
|
-
asset = @cloud[
|
112
|
+
asset = @cloud["dog_pound/dogs.xml"]
|
112
113
|
|
113
114
|
expect(asset).to(respond_to(:my_unimplemented_extension))
|
114
115
|
expect { asset.my_unimplemented_extension }.to(raise_error(NotImplementedError))
|