kvom 6.8.0.beta.200.809.bdfa8c3 → 6.8.0.beta.200.856.8c0fec5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -3
- data/kvom.gemspec +6 -6
- data/lib/kvom.rb +2 -1
- data/lib/kvom/adapter.rb +4 -4
- data/lib/kvom/adapter/base.rb +5 -0
- data/lib/kvom/adapter/couchdb_adapter.rb +18 -16
- data/lib/kvom/adapter/couchdb_document.rb +6 -2
- data/lib/kvom/adapter/dynamodb_adapter.rb +6 -2
- data/lib/kvom/adapter/dynamodb_document.rb +27 -51
- data/lib/kvom/adapter/filesystem_adapter.rb +130 -0
- data/lib/kvom/adapter/filesystem_document.rb +11 -0
- data/lib/kvom/adapter/key_attributes_document.rb +26 -0
- data/lib/kvom/base.rb +3 -0
- data/lib/kvom/document.rb +7 -1
- data/lib/kvom/lib.rb +5 -0
- data/lib/kvom/lib/json.rb +14 -0
- data/lib/kvom/lib/json_value.rb +39 -0
- data/lib/kvom/model_identity.rb +2 -0
- data/lib/kvom/not_found.rb +2 -0
- data/lib/kvom/storage.rb +4 -4
- data/lib/kvom/storage/base.rb +50 -72
- data/lib/kvom/storage/cache_with_prefix.rb +7 -1
- data/lib/kvom/storage/file_system_storage.rb +18 -17
- data/lib/kvom/storage/not_found.rb +3 -6
- data/lib/kvom/storage/s3_storage.rb +55 -53
- data/spec/adaptor/base_spec.rb +87 -0
- data/spec/lib/json_spec.rb +30 -0
- data/spec/spec_helper.rb +15 -3
- data/tmp/.gitignore +3 -0
- metadata +47 -52
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'kvom'
|
2
|
+
|
3
|
+
module Kvom; module Adapter;
|
4
|
+
|
5
|
+
class KeyAttributesDocument < Document
|
6
|
+
|
7
|
+
attr_reader :key, :attributes
|
8
|
+
|
9
|
+
def initialize(key, attributes)
|
10
|
+
@key = key
|
11
|
+
@attributes = attributes || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](name)
|
15
|
+
@attributes ||= load_attributes
|
16
|
+
@attributes[name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(name, value)
|
20
|
+
@attributes ||= load_attributes
|
21
|
+
@attributes[name] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end; end # module Kvom::Adapter
|
data/lib/kvom/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'kvom'
|
1
2
|
require 'active_support/core_ext/hash/keys'
|
2
3
|
require 'active_support/core_ext/object/blank'
|
3
4
|
require 'active_support/core_ext/class/attribute'
|
@@ -7,6 +8,7 @@ require 'securerandom'
|
|
7
8
|
module Kvom
|
8
9
|
|
9
10
|
class Base
|
11
|
+
|
10
12
|
include ModelIdentity
|
11
13
|
extend ActiveModel::Naming
|
12
14
|
|
@@ -102,6 +104,7 @@ class Base
|
|
102
104
|
def destroy
|
103
105
|
self.class.adapter.destroy(@document)
|
104
106
|
end
|
107
|
+
|
105
108
|
end
|
106
109
|
|
107
110
|
end # module Kvom
|
data/lib/kvom/document.rb
CHANGED
data/lib/kvom/lib.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'kvom/lib'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
::Kvom::Lib::Json = ::MultiJson if (%w[dump load] - ::MultiJson.singleton_methods).empty?
|
5
|
+
|
6
|
+
module Kvom::Lib::Json
|
7
|
+
def self.dump(*args)
|
8
|
+
::MultiJson.encode(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.load(*args)
|
12
|
+
::MultiJson.decode(*args)
|
13
|
+
end
|
14
|
+
end unless defined?(Kvom::Lib::Json)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'kvom/lib'
|
2
|
+
|
3
|
+
module Kvom; module Lib
|
4
|
+
|
5
|
+
module JsonValue
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# all special cases are just a shortcut
|
9
|
+
def dump(primitive)
|
10
|
+
case primitive
|
11
|
+
when nil
|
12
|
+
"null"
|
13
|
+
when true, false
|
14
|
+
primitive.to_s
|
15
|
+
when ""
|
16
|
+
'""'
|
17
|
+
else
|
18
|
+
Json.dump([primitive])[1..-2]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def load(jsonvalue_string)
|
23
|
+
case jsonvalue_string
|
24
|
+
when "null"
|
25
|
+
nil
|
26
|
+
when "true"
|
27
|
+
true
|
28
|
+
when "false"
|
29
|
+
false
|
30
|
+
when '""'
|
31
|
+
""
|
32
|
+
else
|
33
|
+
Json.load("[#{jsonvalue_string}]").first
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end; end # module Kvom::Lib
|
data/lib/kvom/model_identity.rb
CHANGED
data/lib/kvom/not_found.rb
CHANGED
data/lib/kvom/storage.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require 'kvom'
|
2
|
+
|
3
|
+
module Kvom::Storage
|
4
|
+
Kvom.setup_autoload(self, __FILE__)
|
5
5
|
end
|
data/lib/kvom/storage/base.rb
CHANGED
@@ -1,88 +1,66 @@
|
|
1
|
+
require 'kvom/storage'
|
2
|
+
|
1
3
|
require 'securerandom'
|
2
4
|
require 'multi_json'
|
3
5
|
require 'active_support/core_ext/hash/keys'
|
4
6
|
|
5
|
-
module Kvom
|
6
|
-
module Storage
|
7
|
-
if MultiJson.respond_to?(:dump)
|
8
|
-
module MultiJsonCoder
|
9
|
-
def encode(value)
|
10
|
-
MultiJson.dump(value)
|
11
|
-
end
|
7
|
+
module Kvom; module Storage
|
12
8
|
|
13
|
-
|
14
|
-
MultiJson.load(value)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
else
|
18
|
-
module MultiJsonCoder
|
19
|
-
def encode(value)
|
20
|
-
MultiJson.encode(value)
|
21
|
-
end
|
9
|
+
class Base
|
22
10
|
|
23
|
-
|
24
|
-
MultiJson.decode(value)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
11
|
+
attr_reader :config
|
28
12
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
if config
|
38
|
-
config.symbolize_keys
|
39
|
-
else
|
40
|
-
{}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def put(data)
|
45
|
-
id = generate_id
|
46
|
-
json_string = encode(data)
|
47
|
-
normalized = decode(json_string)
|
48
|
-
write(id, normalized, json_string)
|
49
|
-
{"id" => id}
|
50
|
-
end
|
13
|
+
def initialize(config = nil)
|
14
|
+
@config =
|
15
|
+
if config
|
16
|
+
config.symbolize_keys
|
17
|
+
else
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
51
21
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
spec[:id]
|
60
|
-
else
|
61
|
-
raise "Invalid key spec (no id): #{spec.inspect}"
|
62
|
-
end
|
63
|
-
read(id)
|
64
|
-
end
|
22
|
+
def put(data)
|
23
|
+
id = generate_id
|
24
|
+
json_string = Lib::Json.dump(data)
|
25
|
+
normalized = Lib::Json.load(json_string)
|
26
|
+
write(id, normalized, json_string)
|
27
|
+
{"id" => id}
|
28
|
+
end
|
65
29
|
|
66
|
-
|
30
|
+
def get(spec)
|
31
|
+
raise "Invalid key spec (not a hash): #{spec.inspect}" unless Hash === spec
|
32
|
+
id =
|
33
|
+
case
|
34
|
+
when spec.key?("id")
|
35
|
+
spec["id"]
|
36
|
+
when spec.key?(:id)
|
37
|
+
spec[:id]
|
38
|
+
else
|
39
|
+
raise "Invalid key spec (no id): #{spec.inspect}"
|
40
|
+
end
|
41
|
+
read(id)
|
42
|
+
end
|
67
43
|
|
68
|
-
|
69
|
-
raise "implement me in subclass!"
|
70
|
-
end
|
44
|
+
private
|
71
45
|
|
72
|
-
|
73
|
-
|
74
|
-
|
46
|
+
def write(id, data, json_data)
|
47
|
+
raise "implement me in subclass!"
|
48
|
+
end
|
75
49
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
else
|
81
|
-
def generate_id
|
82
|
-
SecureRandom.urlsafe_base64(15)
|
83
|
-
end
|
84
|
-
end
|
50
|
+
def read(id)
|
51
|
+
raise "implement me in subclass!"
|
52
|
+
end
|
85
53
|
|
54
|
+
if RUBY_VERSION < "1.9.2"
|
55
|
+
def generate_id
|
56
|
+
SecureRandom.base64(15).tr("+/", "-_")
|
57
|
+
end
|
58
|
+
else
|
59
|
+
def generate_id
|
60
|
+
SecureRandom.urlsafe_base64(15)
|
86
61
|
end
|
87
62
|
end
|
63
|
+
|
88
64
|
end
|
65
|
+
|
66
|
+
end; end # module Kvom::Storage
|
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
require 'kvom/storage'
|
2
|
+
|
3
|
+
module Kvom; module Storage
|
4
|
+
|
5
|
+
class CacheWithPrefix
|
2
6
|
|
3
7
|
def initialize(cache, prefix)
|
4
8
|
@prefix = prefix
|
@@ -22,3 +26,5 @@ class Kvom::Storage::CacheWithPrefix
|
|
22
26
|
end
|
23
27
|
|
24
28
|
end
|
29
|
+
|
30
|
+
end; end # module Kvom::Storage
|
@@ -1,27 +1,28 @@
|
|
1
|
+
require 'kvom/storage'
|
1
2
|
# require 'active_support/cache/file_store' # fails to autoload Cache::Store (no separate file)
|
2
3
|
require 'active_support/cache'
|
3
4
|
|
4
|
-
module Kvom
|
5
|
-
module Storage
|
6
|
-
class FileSystemStorage < Base
|
7
|
-
def initialize(options)
|
8
|
-
super
|
9
|
-
path = config[:path] or raise "No path specified"
|
10
|
-
@storage = ActiveSupport::Cache::FileStore.new(path, options)
|
11
|
-
end
|
5
|
+
module Kvom; module Storage
|
12
6
|
|
13
|
-
|
7
|
+
class FileSystemStorage < Base
|
8
|
+
def initialize(options)
|
9
|
+
super
|
10
|
+
path = config[:path] or raise "No path specified"
|
11
|
+
@storage = ActiveSupport::Cache::FileStore.new(path, options)
|
12
|
+
end
|
14
13
|
|
15
|
-
|
14
|
+
private
|
16
15
|
|
17
|
-
|
18
|
-
storage.read(id)
|
19
|
-
end
|
16
|
+
attr_reader :storage
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
def read(id)
|
19
|
+
storage.read(id)
|
20
|
+
end
|
24
21
|
|
25
|
-
|
22
|
+
def write(id, value, ignored_json_string)
|
23
|
+
storage.write(id, value)
|
26
24
|
end
|
25
|
+
|
27
26
|
end
|
27
|
+
|
28
|
+
end; end # module Kvom::Storage
|
@@ -1,73 +1,75 @@
|
|
1
|
+
require 'kvom/storage'
|
1
2
|
require 'multi_json'
|
2
3
|
require 'aws-sdk'
|
3
4
|
|
4
|
-
module
|
5
|
-
class S3Storage < Base
|
6
|
-
|
7
|
-
def initialize(options)
|
8
|
-
super
|
9
|
-
@bucket = config[:bucket] or raise "No bucket specified"
|
10
|
-
if "" != (bucket_prefix = config[:bucket_prefix].to_s)
|
11
|
-
@bucket_prefix = bucket_prefix
|
12
|
-
end
|
13
|
-
|
14
|
-
if (cache = config[:cache])
|
15
|
-
cache_prefix = config[:cache_prefix].to_s
|
16
|
-
@cache =
|
17
|
-
if "" != cache_prefix
|
18
|
-
CacheWithPrefix.new(cache, cache_prefix)
|
19
|
-
else
|
20
|
-
cache
|
21
|
-
end
|
22
|
-
extend CacheAware
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
5
|
+
module Kvom; module Storage
|
27
6
|
|
28
|
-
|
7
|
+
class S3Storage < Base
|
29
8
|
|
30
|
-
|
31
|
-
|
9
|
+
def initialize(options)
|
10
|
+
super
|
11
|
+
@bucket = config[:bucket] or raise "No bucket specified"
|
12
|
+
if "" != (bucket_prefix = config[:bucket_prefix].to_s)
|
13
|
+
@bucket_prefix = bucket_prefix
|
32
14
|
end
|
33
15
|
|
34
|
-
|
35
|
-
|
16
|
+
if (cache = config[:cache])
|
17
|
+
cache_prefix = config[:cache_prefix].to_s
|
18
|
+
@cache =
|
19
|
+
if "" != cache_prefix
|
20
|
+
CacheWithPrefix.new(cache, cache_prefix)
|
21
|
+
else
|
22
|
+
cache
|
23
|
+
end
|
24
|
+
extend S3Storage::CacheAware
|
36
25
|
end
|
26
|
+
end
|
37
27
|
|
38
|
-
|
39
|
-
s3_object(id).read
|
40
|
-
rescue AWS::S3::Errors::NoSuchKey => e
|
41
|
-
e.extend NotFound
|
42
|
-
raise e
|
43
|
-
end
|
28
|
+
private
|
44
29
|
|
45
|
-
|
46
|
-
@s3_objects ||= bucket.objects
|
47
|
-
s3_id = bucket_prefix ? "#{bucket_prefix}/#{id}" : id
|
48
|
-
@s3_objects[s3_id]
|
49
|
-
end
|
30
|
+
attr_reader :bucket, :bucket_prefix, :cache
|
50
31
|
|
51
|
-
|
32
|
+
def read(id)
|
33
|
+
Lib::Json.load(s3_read(id))
|
34
|
+
end
|
52
35
|
|
53
|
-
|
36
|
+
def write(id, object, json_string)
|
37
|
+
s3_object(id).write(json_string)
|
38
|
+
end
|
54
39
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
object
|
62
|
-
end
|
40
|
+
def s3_read(id)
|
41
|
+
s3_object(id).read
|
42
|
+
rescue AWS::S3::Errors::NoSuchKey => e
|
43
|
+
e.extend NotFound
|
44
|
+
raise e
|
45
|
+
end
|
63
46
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
47
|
+
def s3_object(id)
|
48
|
+
@s3_objects ||= bucket.objects
|
49
|
+
s3_id = bucket_prefix ? "#{bucket_prefix}/#{id}" : id
|
50
|
+
@s3_objects[s3_id]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
module S3Storage::CacheAware
|
68
56
|
|
57
|
+
private
|
58
|
+
|
59
|
+
def read(id)
|
60
|
+
object = cache.read(id)
|
61
|
+
if nil == object
|
62
|
+
object = super
|
63
|
+
cache.write(id, object)
|
69
64
|
end
|
65
|
+
object
|
66
|
+
end
|
70
67
|
|
68
|
+
def write(id, object, json_string)
|
69
|
+
super
|
70
|
+
cache.write(id, object)
|
71
71
|
end
|
72
72
|
|
73
73
|
end
|
74
|
+
|
75
|
+
end; end # module Kvom::Storage
|