asset_cloud 2.7.1 → 2.7.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 +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/lib/asset_cloud/bucket.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class AssetNotFoundError < StandardError
|
3
|
-
def initialize(key, version=nil)
|
5
|
+
def initialize(key, version = nil)
|
4
6
|
super(version ? "Could not find version #{version} of asset #{key}" : "Could not find asset #{key}")
|
5
7
|
end
|
6
8
|
end
|
@@ -10,7 +12,8 @@ module AssetCloud
|
|
10
12
|
attr_accessor :cloud
|
11
13
|
|
12
14
|
def initialize(cloud, name)
|
13
|
-
@cloud
|
15
|
+
@cloud = cloud
|
16
|
+
@name = name
|
14
17
|
end
|
15
18
|
|
16
19
|
def ls(key = nil)
|
@@ -1,35 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class ActiveRecordBucket < AssetCloud::Bucket
|
3
5
|
class_attribute :key_attribute, :value_attribute
|
4
|
-
self.key_attribute =
|
5
|
-
self.value_attribute =
|
6
|
+
self.key_attribute = "key"
|
7
|
+
self.value_attribute = "value"
|
6
8
|
|
7
|
-
def ls(key=name)
|
8
|
-
col = records.connection.quote_column_name(
|
9
|
-
records.all(:
|
10
|
-
cloud[r.send(
|
9
|
+
def ls(key = name)
|
10
|
+
col = records.connection.quote_column_name(key_attribute)
|
11
|
+
records.all(conditions: ["#{col} LIKE ?", "#{key}%"]).map do |r|
|
12
|
+
cloud[r.send(key_attribute)]
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
16
|
def read(key)
|
15
|
-
find_record!(key).send(
|
17
|
+
find_record!(key).send(value_attribute)
|
16
18
|
end
|
17
19
|
|
18
20
|
def write(key, value)
|
19
|
-
record = records.send("find_or_initialize_by_#{
|
20
|
-
record.send("#{
|
21
|
+
record = records.send("find_or_initialize_by_#{key_attribute}", key.to_s)
|
22
|
+
record.send("#{value_attribute}=", value)
|
21
23
|
record.save!
|
22
24
|
end
|
23
25
|
|
24
26
|
def delete(key)
|
25
|
-
if record = find_record(key)
|
27
|
+
if (record = find_record(key))
|
26
28
|
record.destroy
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def stat(key)
|
31
|
-
if record = find_record(key)
|
32
|
-
AssetCloud::Metadata.new(true, record.send(
|
33
|
+
if (record = find_record(key))
|
34
|
+
AssetCloud::Metadata.new(true, record.send(value_attribute).size, record.created_at, record.updated_at)
|
33
35
|
else
|
34
36
|
AssetCloud::Metadata.new(false)
|
35
37
|
end
|
@@ -47,11 +49,11 @@ module AssetCloud
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def find_record(key)
|
50
|
-
records.first(:
|
52
|
+
records.first(conditions: { key_attribute => key.to_s })
|
51
53
|
end
|
52
54
|
|
53
55
|
def find_record!(key)
|
54
|
-
find_record(key)
|
56
|
+
find_record(key) || raise(AssetCloud::AssetNotFoundError, key)
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -1,61 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class BucketChain < Bucket
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
class << self
|
6
|
+
# returns a new Bucket class which writes to each given Bucket
|
7
|
+
# but only uses the first one for reading
|
8
|
+
def chain(*klasses)
|
9
|
+
Class.new(self) do
|
10
|
+
attr_reader :chained_buckets
|
11
|
+
|
12
|
+
define_method "initialize" do |cloud, name|
|
13
|
+
super(cloud, name)
|
14
|
+
@chained_buckets = klasses.map { |klass| klass.new(cloud, name) }
|
15
|
+
end
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
14
19
|
|
15
|
-
def ls(key=nil)
|
16
|
-
first_possible_bucket {|b| b.ls(key)}
|
20
|
+
def ls(key = nil)
|
21
|
+
first_possible_bucket { |b| b.ls(key) }
|
17
22
|
end
|
23
|
+
|
18
24
|
def read(key)
|
19
|
-
first_possible_bucket {|b| b.read(key)}
|
25
|
+
first_possible_bucket { |b| b.read(key) }
|
20
26
|
end
|
21
|
-
|
22
|
-
|
27
|
+
|
28
|
+
def stat(key = nil)
|
29
|
+
first_possible_bucket { |b| b.stat(key) }
|
23
30
|
end
|
31
|
+
|
24
32
|
def read_version(key, version)
|
25
|
-
first_possible_bucket {|b| b.read_version(key, version)}
|
33
|
+
first_possible_bucket { |b| b.read_version(key, version) }
|
26
34
|
end
|
35
|
+
|
27
36
|
def versions(key)
|
28
|
-
first_possible_bucket {|b| b.versions(key)}
|
37
|
+
first_possible_bucket { |b| b.versions(key) }
|
29
38
|
end
|
30
39
|
|
31
40
|
def write(key, data)
|
32
|
-
every_bucket_with_transaction_on_key(key) {|b| b.write(key, data)}
|
41
|
+
every_bucket_with_transaction_on_key(key) { |b| b.write(key, data) }
|
33
42
|
end
|
43
|
+
|
34
44
|
def delete(key)
|
35
|
-
every_bucket_with_transaction_on_key(key) {|b| b.delete(key)}
|
45
|
+
every_bucket_with_transaction_on_key(key) { |b| b.delete(key) }
|
36
46
|
end
|
37
47
|
|
38
|
-
def
|
39
|
-
@chained_buckets.any? {|b| b.respond_to?(sym)}
|
48
|
+
def respond_to_missing?(sym, *)
|
49
|
+
@chained_buckets.any? { |b| b.respond_to?(sym) }
|
40
50
|
end
|
51
|
+
|
41
52
|
def method_missing(sym, *args)
|
42
|
-
first_possible_bucket {|b| b.send(sym, *args)}
|
53
|
+
first_possible_bucket { |b| b.send(sym, *args) }
|
43
54
|
end
|
44
55
|
|
45
56
|
private
|
46
57
|
|
47
58
|
def first_possible_bucket(&block)
|
48
59
|
@chained_buckets.each do |bucket|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
nil
|
53
|
-
end
|
60
|
+
return yield(bucket)
|
61
|
+
rescue NoMethodError, NotImplementedError
|
62
|
+
nil
|
54
63
|
end
|
55
64
|
end
|
56
65
|
|
57
|
-
def every_bucket_with_transaction_on_key(key, i=0, &block)
|
58
|
-
return unless bucket = @chained_buckets[i]
|
66
|
+
def every_bucket_with_transaction_on_key(key, i = 0, &block)
|
67
|
+
return unless (bucket = @chained_buckets[i])
|
59
68
|
|
60
69
|
old_value = begin
|
61
70
|
bucket.read(key)
|
@@ -65,8 +74,8 @@ module AssetCloud
|
|
65
74
|
result = yield(bucket)
|
66
75
|
|
67
76
|
begin
|
68
|
-
every_bucket_with_transaction_on_key(key, i+1, &block)
|
69
|
-
|
77
|
+
every_bucket_with_transaction_on_key(key, i + 1, &block)
|
78
|
+
result
|
70
79
|
rescue StandardError => e
|
71
80
|
if old_value
|
72
81
|
bucket.write(key, old_value)
|
@@ -76,7 +85,5 @@ module AssetCloud
|
|
76
85
|
raise e
|
77
86
|
end
|
78
87
|
end
|
79
|
-
|
80
88
|
end
|
81
|
-
|
82
89
|
end
|
@@ -1,27 +1,29 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module AssetCloud
|
3
4
|
class FileSystemBucket < Bucket
|
4
|
-
|
5
5
|
def ls(key = nil)
|
6
6
|
objects = []
|
7
|
-
base_path = File.join(path_for(key),
|
7
|
+
base_path = File.join(path_for(key), "*")
|
8
8
|
|
9
9
|
Dir.glob(base_path).each do |f|
|
10
10
|
next unless File.file?(f)
|
11
|
-
|
11
|
+
|
12
|
+
objects.push(cloud[relative_path_for(f)])
|
12
13
|
end
|
13
14
|
objects
|
14
15
|
end
|
15
16
|
|
16
17
|
def read(key)
|
17
18
|
File.read(path_for(key))
|
18
|
-
rescue Errno::ENOENT
|
19
|
+
rescue Errno::ENOENT
|
19
20
|
raise AssetCloud::AssetNotFoundError, key
|
20
21
|
end
|
21
22
|
|
22
23
|
def delete(key)
|
23
24
|
File.delete(path_for(key))
|
24
25
|
rescue Errno::ENOENT
|
26
|
+
nil
|
25
27
|
end
|
26
28
|
|
27
29
|
def write(key, data)
|
@@ -32,12 +34,10 @@ module AssetCloud
|
|
32
34
|
end
|
33
35
|
|
34
36
|
def stat(key)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
Metadata.new(false)
|
40
|
-
end
|
37
|
+
stat = File.stat(path_for(key))
|
38
|
+
Metadata.new(true, stat.size, stat.ctime, stat.mtime)
|
39
|
+
rescue Errno::ENOENT
|
40
|
+
Metadata.new(false)
|
41
41
|
end
|
42
42
|
|
43
43
|
protected
|
@@ -53,11 +53,11 @@ module AssetCloud
|
|
53
53
|
private
|
54
54
|
|
55
55
|
def remove_full_path_regexp
|
56
|
-
@regexp ||=
|
56
|
+
@regexp ||= %r{^#{path}/}
|
57
57
|
end
|
58
58
|
|
59
59
|
def relative_path_for(f)
|
60
|
-
f.sub(remove_full_path_regexp,
|
60
|
+
f.sub(remove_full_path_regexp, "")
|
61
61
|
end
|
62
62
|
|
63
63
|
def execute_in_full_path(key, &block)
|
@@ -71,10 +71,9 @@ module AssetCloud
|
|
71
71
|
|
72
72
|
begin
|
73
73
|
yield(path)
|
74
|
-
rescue Errno::ENOENT
|
74
|
+
rescue Errno::ENOENT
|
75
75
|
raise if retried
|
76
76
|
|
77
|
-
directory = File.dirname(path)
|
78
77
|
FileUtils.mkdir_p(File.dirname(path))
|
79
78
|
retried = true
|
80
79
|
retry
|
@@ -31,12 +31,10 @@ module AssetCloud
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def stat(key)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
Metadata.new(false)
|
39
|
-
end
|
34
|
+
file = find_by_key!(key)
|
35
|
+
Metadata.new(true, file.size, file.created_at, file.updated_at)
|
36
|
+
rescue AssetCloud::AssetNotFoundError
|
37
|
+
Metadata.new(false)
|
40
38
|
end
|
41
39
|
|
42
40
|
private
|
@@ -47,11 +45,11 @@ module AssetCloud
|
|
47
45
|
|
48
46
|
def absolute_key(key = nil)
|
49
47
|
if key.to_s.starts_with?(path_prefix)
|
50
|
-
|
48
|
+
key
|
51
49
|
else
|
52
50
|
args = [path_prefix]
|
53
51
|
args << key.to_s if key
|
54
|
-
args.join(
|
52
|
+
args.join("/")
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
@@ -1,28 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class InvalidBucketError < StandardError
|
3
5
|
end
|
4
6
|
|
5
7
|
class InvalidBucket < Bucket
|
6
|
-
|
8
|
+
ERROR = "No such namespace: %s"
|
9
|
+
private_constant :ERROR
|
7
10
|
|
8
11
|
def ls(namespace)
|
9
|
-
raise InvalidBucketError,
|
12
|
+
raise InvalidBucketError, ERROR % namespace
|
10
13
|
end
|
11
14
|
|
12
15
|
def read(key)
|
13
|
-
raise InvalidBucketError,
|
16
|
+
raise InvalidBucketError, ERROR % key
|
14
17
|
end
|
15
18
|
|
16
19
|
def write(key, data)
|
17
|
-
raise InvalidBucketError,
|
20
|
+
raise InvalidBucketError, ERROR % key
|
18
21
|
end
|
19
22
|
|
20
23
|
def delete(key)
|
21
|
-
raise InvalidBucketError,
|
24
|
+
raise InvalidBucketError, ERROR % key
|
22
25
|
end
|
23
26
|
|
24
27
|
def stat(key)
|
25
|
-
raise InvalidBucketError,
|
28
|
+
raise InvalidBucketError, ERROR % key
|
26
29
|
end
|
27
30
|
end
|
28
31
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AssetCloud
|
2
4
|
class MemoryBucket < Bucket
|
3
5
|
def initialize(*args)
|
@@ -5,16 +7,17 @@ module AssetCloud
|
|
5
7
|
@memory = {}
|
6
8
|
end
|
7
9
|
|
8
|
-
def ls(prefix=nil)
|
10
|
+
def ls(prefix = nil)
|
9
11
|
results = []
|
10
|
-
@memory.each do |k,
|
12
|
+
@memory.each do |k, _v|
|
11
13
|
results.push(cloud[k]) if prefix.nil? || k.starts_with?(prefix)
|
12
14
|
end
|
13
15
|
results
|
14
16
|
end
|
15
17
|
|
16
18
|
def read(key)
|
17
|
-
raise AssetCloud::AssetNotFoundError, key unless @memory.
|
19
|
+
raise AssetCloud::AssetNotFoundError, key unless @memory.key?(key)
|
20
|
+
|
18
21
|
@memory[key]
|
19
22
|
end
|
20
23
|
|
@@ -29,7 +32,7 @@ module AssetCloud
|
|
29
32
|
end
|
30
33
|
|
31
34
|
def stat(key)
|
32
|
-
return Metadata.non_existing unless @memory.
|
35
|
+
return Metadata.non_existing unless @memory.key?(key)
|
33
36
|
|
34
37
|
Metadata.new(true, read(key).size)
|
35
38
|
end
|
@@ -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
|
@@ -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,7 +61,6 @@ module AssetCloud
|
|
59
61
|
|
60
62
|
def execute_callbacks(symbol, args)
|
61
63
|
callbacks_for(symbol).each do |callback|
|
62
|
-
|
63
64
|
result = case callback
|
64
65
|
when Symbol
|
65
66
|
send(callback, *args)
|
@@ -69,7 +70,10 @@ module AssetCloud
|
|
69
70
|
if callback.respond_to?(symbol)
|
70
71
|
callback.send(symbol, self, *args)
|
71
72
|
else
|
72
|
-
raise StandardError,
|
73
|
+
raise StandardError,
|
74
|
+
"Callbacks must be a symbol denoting the method to call, " \
|
75
|
+
"a string to be evaluated, a block to be invoked, " \
|
76
|
+
"or an object responding to the callback method."
|
73
77
|
end
|
74
78
|
end
|
75
79
|
return false if result == false
|
@@ -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,31 +1,33 @@
|
|
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
|
@@ -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
|