hypostasis 0.1.0 → 0.1.1
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/lib/hypostasis.rb +2 -0
- data/lib/hypostasis/data_models/document.rb +14 -0
- data/lib/hypostasis/document.rb +121 -0
- data/lib/hypostasis/errors.rb +1 -0
- data/lib/hypostasis/namespace.rb +7 -1
- data/lib/hypostasis/version.rb +1 -1
- data/test/document_spec.rb +50 -0
- data/test/minitest_helper.rb +2 -0
- data/test/support/sample_document.rb +9 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb31443e0e30e596eee33533e9bf70bf207df3b6
|
4
|
+
data.tar.gz: b5753b79d36c1fec6000a0bb20bac292383b0db7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72f6be472948ea18c1ac60df3d8503f61cc58be05f20a572b7d81a5a626dbe826ce7f5ad89513aa13f8396d89ba0762d5006a3796a66c8c8b5d385b52d590c3e
|
7
|
+
data.tar.gz: 492764de3d86804dd84e195944b3c3b2cbc9bf144ecb60e50f5fd6db92e75888a9274275c20d9e91d09189a53b39943b617b818e8d7b4667ceb3fcc940df8e65
|
data/lib/hypostasis.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
1
|
module Hypostasis::DataModels::Document
|
2
|
+
def transact
|
3
|
+
database.transact do |tr|
|
4
|
+
yield tr
|
5
|
+
end
|
6
|
+
end
|
2
7
|
|
8
|
+
def for_document(document, id = nil)
|
9
|
+
class_name = document.is_a?(Class) ? document.to_s : document.class.to_s
|
10
|
+
document_id = id.nil? ? document.id.to_s : id.to_s
|
11
|
+
name.to_s + '\\' + Hypostasis::Tuple.new(class_name, document_id).to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def for_field(document, field, type)
|
15
|
+
for_document(document) + '\\' + Hypostasis::Tuple.new(field.to_s, type.to_s).to_s
|
16
|
+
end
|
3
17
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Hypostasis::Document
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
base.class_eval do
|
5
|
+
attr_reader :id
|
6
|
+
# Register somewhere?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(*attributes)
|
11
|
+
self.class.namespace.open
|
12
|
+
|
13
|
+
@fields = {}
|
14
|
+
self.class.fields.each {|name| @fields[name] = nil}
|
15
|
+
attributes.each {|hsh| hsh.each {|name, value| @fields[name.to_sym] = value}}
|
16
|
+
end
|
17
|
+
|
18
|
+
def save
|
19
|
+
generate_id
|
20
|
+
self.class.namespace.transact do |tr|
|
21
|
+
tr.set(self.class.namespace.for_document(self), true.to_s)
|
22
|
+
|
23
|
+
@fields.each do |field_name, value|
|
24
|
+
tr.set(self.class.namespace.for_field(self, field_name, value.class.to_s), value.to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_id
|
31
|
+
@id ||= SecureRandom.uuid
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_id(id)
|
35
|
+
@id ||= id.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
def use_namespace(namespace)
|
40
|
+
@@namespace = Hypostasis::Namespace.new(namespace.to_s, :document)
|
41
|
+
end
|
42
|
+
|
43
|
+
def namespace
|
44
|
+
@@namespace
|
45
|
+
end
|
46
|
+
|
47
|
+
def supported_field_types
|
48
|
+
@@supported_field_types ||= %w{Fixnum Bignum String Integer Float Date DateTime Time Boolean}
|
49
|
+
end
|
50
|
+
|
51
|
+
def field(name, options = {})
|
52
|
+
named = name.to_s
|
53
|
+
raise Hypostasis::Errors::MustDefineFieldType if options[:type].nil?
|
54
|
+
raise Hypostasis::Errors::UnsupportedFieldType unless supported_field_types.include?(options[:type].to_s)
|
55
|
+
register_field(name.to_sym)
|
56
|
+
create_accessors(named, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def fields
|
60
|
+
@@fields
|
61
|
+
end
|
62
|
+
|
63
|
+
def register_field(name)
|
64
|
+
@@fields = [] unless defined?(@@fields)
|
65
|
+
@@fields << name.to_sym
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_accessors(name, options)
|
69
|
+
self.class_eval do
|
70
|
+
define_method(name) { @fields[name.to_sym] || nil }
|
71
|
+
define_method("#{name}=") {|value| @fields[name.to_sym] = value}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def find(id)
|
76
|
+
document_keys = []
|
77
|
+
namespace.transact do |tr|
|
78
|
+
document_keys = tr.get_range_start_with(namespace.for_document(self, id))
|
79
|
+
end
|
80
|
+
#raise Hypostasis::Errors::DocumentNotFound if document_keys.empty?
|
81
|
+
attributes = {}
|
82
|
+
id = Hypostasis::Tuple.unpack(document_keys.first.key.split('\\')[1]).to_a[1]
|
83
|
+
document_keys.each do |key|
|
84
|
+
attribute_tuple = key.key.split('\\')[2]
|
85
|
+
next if attribute_tuple.nil?
|
86
|
+
unpacked_key = Hypostasis::Tuple.unpack(attribute_tuple)
|
87
|
+
raw_value = key.value
|
88
|
+
attributes[unpacked_key.to_a[0].to_sym] = reconstitute_value(unpacked_key, raw_value)
|
89
|
+
end
|
90
|
+
document = self.new(attributes)
|
91
|
+
document.set_id(id)
|
92
|
+
document
|
93
|
+
end
|
94
|
+
|
95
|
+
def reconstitute_value(tuple, raw_value)
|
96
|
+
data_type = tuple.to_a.last
|
97
|
+
case data_type
|
98
|
+
when 'Fixnum'
|
99
|
+
Integer(raw_value)
|
100
|
+
when 'Bignum'
|
101
|
+
Integer(raw_value)
|
102
|
+
when 'Float'
|
103
|
+
Float(raw_value)
|
104
|
+
when 'String'
|
105
|
+
raw_value
|
106
|
+
when 'Date'
|
107
|
+
Date.parse(raw_value)
|
108
|
+
when 'DateTime'
|
109
|
+
DateTime.parse(raw_value)
|
110
|
+
when 'Time'
|
111
|
+
Time.parse(raw_value)
|
112
|
+
when 'TrueClass'
|
113
|
+
true
|
114
|
+
when 'FalseClass'
|
115
|
+
false
|
116
|
+
else
|
117
|
+
raise Hypostasis::Errors::UnknownValueType
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/hypostasis/errors.rb
CHANGED
data/lib/hypostasis/namespace.rb
CHANGED
@@ -4,10 +4,16 @@ class Hypostasis::Namespace
|
|
4
4
|
def initialize(name, data_model = :key_value)
|
5
5
|
@name = name.to_s
|
6
6
|
@data_model = data_model.to_sym
|
7
|
-
|
8
7
|
load_data_model
|
9
8
|
end
|
10
9
|
|
10
|
+
def open
|
11
|
+
raise Hypostasis::Errors::NonExistentNamespace if database[name].nil?
|
12
|
+
data_model = database.get(name + '\\' + Hypostasis::Tuple.new('config','data_model').to_s)
|
13
|
+
raise Hypostasis::Errors::NamespaceDataModelMismatch if data_model != @data_model.to_s
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
11
17
|
def destroy
|
12
18
|
database.clear_range_start_with(@name)
|
13
19
|
true
|
data/lib/hypostasis/version.rb
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Hypostasis::Document do
|
4
|
+
let(:subject) { SampleDocument.new(name: 'John', age: 21, dob: Date.today.prev_year(21)) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Hypostasis::Connection.create_namespace 'sample_docs', data_model: :document
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
Hypostasis::Connection.destroy_namespace 'sample_docs'
|
12
|
+
end
|
13
|
+
|
14
|
+
it { subject.must_respond_to :name }
|
15
|
+
it { subject.must_respond_to :age }
|
16
|
+
it { subject.must_respond_to :dob }
|
17
|
+
|
18
|
+
it { subject.must_respond_to :name= }
|
19
|
+
it { subject.must_respond_to :age= }
|
20
|
+
it { subject.must_respond_to :dob= }
|
21
|
+
|
22
|
+
it { subject.name.must_equal 'John' }
|
23
|
+
it { subject.age.must_equal 21 }
|
24
|
+
it { subject.dob.must_equal Date.today.prev_year(21) }
|
25
|
+
|
26
|
+
it { subject.must_respond_to :save }
|
27
|
+
|
28
|
+
describe '#save' do
|
29
|
+
let(:document_tuple) { Hypostasis::Tuple.new(SampleDocument.to_s, @document.id.to_s).to_s }
|
30
|
+
|
31
|
+
def field_path(name, type)
|
32
|
+
'sample_docs\\' + document_tuple + '\\' + Hypostasis::Tuple.new(name.to_s, type.to_s).to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
before do
|
36
|
+
@document = subject.save
|
37
|
+
end
|
38
|
+
|
39
|
+
it { database.get(field_path(:name, String)).must_equal 'John' }
|
40
|
+
it { database.get(field_path(:age, Fixnum)).must_equal '21' }
|
41
|
+
it { database.get(field_path(:dob, Date)).must_equal Date.today.prev_year(21).to_s }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.find' do
|
45
|
+
let(:document_id) { subject.save.id }
|
46
|
+
|
47
|
+
it { SampleDocument.find(document_id).is_a?(SampleDocument).must_equal true }
|
48
|
+
it { SampleDocument.find(document_id).id.must_equal document_id }
|
49
|
+
end
|
50
|
+
end
|
data/test/minitest_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hypostasis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Thompson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fdb
|
@@ -86,15 +86,18 @@ files:
|
|
86
86
|
- lib/hypostasis/data_models.rb
|
87
87
|
- lib/hypostasis/data_models/document.rb
|
88
88
|
- lib/hypostasis/data_models/key_value.rb
|
89
|
+
- lib/hypostasis/document.rb
|
89
90
|
- lib/hypostasis/errors.rb
|
90
91
|
- lib/hypostasis/key_path.rb
|
91
92
|
- lib/hypostasis/namespace.rb
|
92
93
|
- lib/hypostasis/tuple.rb
|
93
94
|
- lib/hypostasis/version.rb
|
94
95
|
- test/connection_spec.rb
|
96
|
+
- test/document_spec.rb
|
95
97
|
- test/key_path_spec.rb
|
96
98
|
- test/minitest_helper.rb
|
97
99
|
- test/namespace_spec.rb
|
100
|
+
- test/support/sample_document.rb
|
98
101
|
- test/tuple_spec.rb
|
99
102
|
homepage: ''
|
100
103
|
licenses:
|
@@ -116,13 +119,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
119
|
version: '0'
|
117
120
|
requirements: []
|
118
121
|
rubyforge_project:
|
119
|
-
rubygems_version: 2.1
|
122
|
+
rubygems_version: 2.2.1
|
120
123
|
signing_key:
|
121
124
|
specification_version: 4
|
122
125
|
summary: A layer for FoundationDB providing multiple data models for Ruby.
|
123
126
|
test_files:
|
124
127
|
- test/connection_spec.rb
|
128
|
+
- test/document_spec.rb
|
125
129
|
- test/key_path_spec.rb
|
126
130
|
- test/minitest_helper.rb
|
127
131
|
- test/namespace_spec.rb
|
132
|
+
- test/support/sample_document.rb
|
128
133
|
- test/tuple_spec.rb
|