hypostasis 0.0.2 → 0.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 490693935730e28be31a446231221acbfab3ad1b
4
- data.tar.gz: 43b5d9cface98769d770318c6f864708bf27d417
3
+ metadata.gz: 9dbac3fb199bc4d6edf4065159d9ec92e41b071b
4
+ data.tar.gz: 06a5045d627c2b6a0e3e9d95f14ca106c0b95ce7
5
5
  SHA512:
6
- metadata.gz: 6e126c676cd74dff9dae11c287b7fde193c159df9e1e64a55407e7248f548359ce57a693cf8c167e79c40bfacc7c4add9f03b58cdb799d46ef753ea44553a0ec
7
- data.tar.gz: 268813a84afba95aaec59ed7bc6a017ebe3762fe32d50e2613d3009c5730cdf38d91e8853d4a01e1623107c1559a96da86ffbcd1fbca5a4242d6968b9e5277f3
6
+ metadata.gz: 4e378bc61f2ffd706f4a3824292cdc55b14712beab90a7e4bfd5210ca1623047599e34643039edf9700dd4b96bf2e56dd61fcb0c3f59ec16318be10fa477000f
7
+ data.tar.gz: e6d76b2b7160982607a608a75ab966d59575d3bd53422d142a78145988752f1fbe06f645e2b5c97b01c6762557f22c3503f70bc7a73ba7ac9e344cbb215a854d
data/lib/hypostasis.rb CHANGED
@@ -1,4 +1,10 @@
1
1
  require 'hypostasis/version'
2
2
 
3
+ require 'hypostasis/errors'
4
+
5
+ require 'hypostasis/tuple'
6
+ require 'hypostasis/key_path'
3
7
  require 'hypostasis/connection'
4
8
  require 'hypostasis/namespace'
9
+
10
+ require 'hypostasis/data_models'
@@ -5,10 +5,16 @@ FDB.api_version 100
5
5
  class Hypostasis::Connection
6
6
  attr_reader :database
7
7
 
8
+ @@config_key = Hypostasis::KeyPath.new('hypostasis', 'config', 'namespaces')
9
+
8
10
  def initialize
9
11
  @database = FDB.open
10
12
  end
11
13
 
14
+ def self.config_path
15
+ @@config_key
16
+ end
17
+
12
18
  def get(key)
13
19
  database[key.to_s]
14
20
  end
@@ -20,4 +26,26 @@ class Hypostasis::Connection
20
26
  def unset(key)
21
27
  database.clear(key).nil?
22
28
  end
29
+
30
+ def create_namespace(name, options = {data_model: :key_value})
31
+ path = @@config_key.extend_path(name.to_s).to_s
32
+ raise Hypostasis::Errors::NamespaceAlreadyCreated unless database[path].nil?
33
+ database[path] = Marshal.dump(options)
34
+ Hypostasis::Namespace.new(name, options[:data_model])
35
+ end
36
+
37
+ def open_namespace(name)
38
+ path = @@config_key.extend_path(name.to_s).to_s
39
+ raise Hypostasis::Errors::NonExistentNamespace if database[path].nil?
40
+ options = Marshal.load(database[path])
41
+ Hypostasis::Namespace.new(name, options[:data_model])
42
+ end
43
+
44
+ def destroy_namespace(name)
45
+ path = @@config_key.extend_path(name.to_s).to_s
46
+ raise Hypostasis::Errors::NonExistentNamespace if database[path].nil?
47
+ database.clear_range_start_with(path)
48
+ database.clear_range_start_with(name.to_s)
49
+ true
50
+ end
23
51
  end
@@ -0,0 +1,3 @@
1
+ module Hypostasis::DataModel::Document
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ module Hypostasis::DataModel::KeyValue
2
+
3
+ end
@@ -0,0 +1,4 @@
1
+ module Hypostasis::DataModel; end
2
+
3
+ require 'hypostasis/data_model/document'
4
+ require 'hypostasis/data_model/key_value'
@@ -0,0 +1,8 @@
1
+ module Hypostasis::Errors
2
+ class NamespaceAlreadyCreated < StandardError; end
3
+ class NonExistentNamespace < StandardError; end
4
+ class InvalidKeyPath < StandardError; end
5
+ class KeyPathExhausted < StandardError; end
6
+ class InvalidTuple < StandardError; end
7
+ class TupleExhausted < StandardError; end
8
+ end
@@ -0,0 +1,29 @@
1
+ class Hypostasis::KeyPath
2
+ def initialize(*path)
3
+ @path = path.to_a.flatten
4
+ raise Hypostasis::Errors::InvalidKeyPath if @path.empty?
5
+ self
6
+ end
7
+
8
+ def to_s
9
+ @path.join('\\')
10
+ end
11
+
12
+ def to_a
13
+ @path
14
+ end
15
+
16
+ def extend_path(*extension)
17
+ return self if extension.empty?
18
+ extended_path = @path + extension.to_a
19
+ Hypostasis::KeyPath.new(extended_path)
20
+ end
21
+
22
+ def move_up(count = 0)
23
+ return self if count <= 0
24
+ raise Hypostasis::Errors::KeyPathExhausted if count >= @path.size
25
+ new_path = @path
26
+ new_path.pop(count)
27
+ Hypostasis::KeyPath.new(new_path)
28
+ end
29
+ end
@@ -4,14 +4,13 @@ class Hypostasis::Namespace
4
4
  def initialize(name, data_model)
5
5
  @name = name.to_s
6
6
  @data_model = data_model.to_sym
7
-
8
- #self.setup
9
7
  end
10
8
 
11
- private
12
-
13
- #def setup
14
- #
15
- #end
9
+ def key_path
10
+ @key_path ||= Hypostasis::KeyPath.new(name)
11
+ end
16
12
 
13
+ def config_path
14
+ @config_path ||= Hypostasis::Connection.config_path.extend_path(name)
15
+ end
17
16
  end
@@ -0,0 +1,50 @@
1
+ class Hypostasis::Tuple
2
+ def initialize(*tuple)
3
+ @tuple = tuple.to_a.flatten
4
+ raise Hypostasis::Errors::InvalidTuple if @tuple.empty?
5
+ self
6
+ end
7
+
8
+ def to_a
9
+ @tuple
10
+ end
11
+
12
+ def to_s
13
+ @tuple_str ||= FDB::Tuple.pack(@tuple)
14
+ end
15
+
16
+ def prepend(*prefix)
17
+ return self if prefix.empty?
18
+ prepended_tuple = prefix.to_a + @tuple
19
+ Hypostasis::Tuple.new(prepended_tuple)
20
+ end
21
+
22
+ def append(*extension)
23
+ return self if extension.empty?
24
+ appended_tuple = @tuple + extension.to_a
25
+ Hypostasis::Tuple.new(appended_tuple)
26
+ end
27
+
28
+ def trim(count = 0)
29
+ count = count.to_i
30
+ raise Hypostasis::Errors::TupleExhausted if count.abs > @tuple.size - 1
31
+ trimmed_tuple = @tuple
32
+ if count > 0
33
+ trimmed_tuple.pop(count.abs)
34
+ Hypostasis::Tuple.new(trimmed_tuple)
35
+ elsif count < 0
36
+ trimmed_tuple.shift(count.abs)
37
+ Hypostasis::Tuple.new(trimmed_tuple)
38
+ else
39
+ self
40
+ end
41
+ end
42
+
43
+ def to_range
44
+ FDB::Tuple.range(@tuple)
45
+ end
46
+
47
+ def self.unpack(tuple_string)
48
+ Hypostasis::Tuple.new(FDB::Tuple.unpack(tuple_string))
49
+ end
50
+ end
@@ -1,3 +1,3 @@
1
1
  module Hypostasis
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -7,11 +7,56 @@ describe Hypostasis::Connection do
7
7
  it { subject.must_respond_to :set }
8
8
  it { subject.must_respond_to :unset }
9
9
 
10
- it 'supports simple getting and setting' do
11
- subject.get('test_key').nil?.must_equal true
12
- subject.set('test_key', 'test_value').must_equal true
13
- subject.get('test_key').must_equal 'test_value'
14
- subject.unset('test_key').must_equal true
15
- subject.get('test_key').nil?.must_equal true
10
+ describe '#get and #set' do
11
+ before :each do
12
+ subject.set('preset_key', 'preset_value')
13
+ end
14
+
15
+ after :each do
16
+ subject.unset('preset_key')
17
+ end
18
+
19
+ it { subject.get('invalid_key').nil?.must_equal true }
20
+ it { subject.get('preset_key').must_equal 'preset_value' }
21
+ end
22
+
23
+ describe '#unset' do
24
+ it 'unsets a previously set key' do
25
+ subject.set('preset_key', 'preset_value')
26
+ subject.get('preset_key').must_equal 'preset_value'
27
+ subject.unset('preset_key').must_equal true
28
+ subject.get('preset_key').nil?.must_equal true
29
+ end
30
+
31
+ it 'returns true for an unset key' do
32
+ subject.get('preset_key').nil?.must_equal true
33
+ subject.unset('preset_key').must_equal true
34
+ end
35
+ end
36
+
37
+ describe '#create_namespace' do
38
+ before :each do
39
+ subject.create_namespace('already_created')
40
+ end
41
+
42
+ it { subject.create_namespace('newly_created').is_a?(Hypostasis::Namespace).must_equal true }
43
+ it { lambda { subject.create_namespace('already_created') }.must_raise Hypostasis::Errors::NamespaceAlreadyCreated }
44
+ end
45
+
46
+ describe '#open_namespace' do
47
+ before :each do
48
+ subject.create_namespace('already_created')
49
+ end
50
+
51
+ it { subject.open_namespace('already_created').is_a?(Hypostasis::Namespace).must_equal true }
52
+ end
53
+
54
+ describe '#destroy_namespace' do
55
+ before :each do
56
+ subject.create_namespace('already_created')
57
+ end
58
+
59
+ it { subject.destroy_namespace('already_created').must_equal true }
60
+ it { lambda { subject.destroy_namespace('not_created') }.must_raise Hypostasis::Errors::NonExistentNamespace }
16
61
  end
17
62
  end
@@ -0,0 +1,5 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Hypostasis::DataModel::Document do
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Hypostasis::DataModel::KeyValue do
4
+
5
+ end
@@ -0,0 +1,31 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Hypostasis::KeyPath do
4
+ let(:subject) { Hypostasis::KeyPath.new('hypostasis', 'demo', 'path') }
5
+
6
+ it { lambda { Hypostasis::KeyPath.new }.must_raise Hypostasis::Errors::InvalidKeyPath }
7
+
8
+ it { subject.to_s.must_equal 'hypostasis\demo\path' }
9
+ it { subject.to_a.must_equal %w{hypostasis demo path} }
10
+
11
+ describe '#extend_path' do
12
+ it { subject.extend_path.must_equal subject }
13
+
14
+ it { subject.extend_path('extension').to_s.must_equal 'hypostasis\demo\path\extension' }
15
+ it { subject.extend_path('extension').to_a.must_equal %w{hypostasis demo path extension} }
16
+
17
+ it { subject.extend_path('extension', 'path').to_s.must_equal 'hypostasis\demo\path\extension\path' }
18
+ it { subject.extend_path('extension', 'path').to_a.must_equal %w{hypostasis demo path extension path} }
19
+ end
20
+
21
+ describe '#move_up' do
22
+ it { subject.move_up.must_equal subject }
23
+ it { subject.move_up(0).must_equal subject }
24
+ it { subject.move_up(-1).must_equal subject }
25
+ it { subject.move_up(-2).must_equal subject }
26
+
27
+ it { subject.move_up(1).to_a.must_equal %w{hypostasis demo} }
28
+ it { subject.move_up(2).to_a.must_equal %w{hypostasis} }
29
+ it { lambda { subject.move_up(3) }.must_raise Hypostasis::Errors::KeyPathExhausted }
30
+ end
31
+ end
@@ -12,3 +12,22 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
12
12
  require 'hypostasis'
13
13
 
14
14
  require 'minitest/autorun'
15
+
16
+ class Minitest::Spec
17
+
18
+ after do
19
+ database.get_range_start_with("hypostasis\\config\\namespaces") do |kv|
20
+ namespace = kv.key.gsub("hypostasis\\config\\namespaces\\", '')
21
+ database.clear_range_start_with(namespace)
22
+ end
23
+
24
+ database.clear_range_start_with('hypostasis')
25
+ end
26
+
27
+ private
28
+
29
+ def database
30
+ @database ||= FDB.open
31
+ end
32
+
33
+ end
@@ -9,6 +9,11 @@ describe Hypostasis::Namespace do
9
9
  it { subject.must_respond_to :data_model }
10
10
  it { subject.data_model.must_equal :document }
11
11
 
12
- it "sets 'hypostasis/config/namespaces/demonstration' key"
13
- it "sets 'hypostasis/config/namespaces/demonstration/data_model' key"
12
+ it { subject.must_respond_to :key_path }
13
+ it { subject.key_path.is_a?(Hypostasis::KeyPath).must_equal true }
14
+ it { subject.key_path.to_a.must_equal %w{demonstration} }
15
+
16
+ it { subject.must_respond_to :config_path }
17
+ it { subject.config_path.is_a?(Hypostasis::KeyPath).must_equal true }
18
+ it { subject.config_path.to_a.must_equal %w{hypostasis config namespaces demonstration} }
14
19
  end
@@ -0,0 +1,35 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Hypostasis::Tuple do
4
+ let(:subject) { Hypostasis::Tuple.new('tuple', 'example', 123) }
5
+
6
+ it { subject.must_respond_to :to_a }
7
+ it { subject.must_respond_to :to_s }
8
+ it { subject.must_respond_to :prepend }
9
+ it { subject.must_respond_to :append }
10
+ it { subject.must_respond_to :trim }
11
+
12
+ it { subject.to_a.must_equal ['tuple', 'example', 123] }
13
+ it { subject.to_s.must_equal FDB::Tuple.pack(['tuple', 'example', 123]) }
14
+
15
+ it { subject.prepend('another').is_a?(Hypostasis::Tuple).must_equal true }
16
+ it { subject.prepend('another').to_a.must_equal ['another', 'tuple', 'example', 123] }
17
+
18
+ it { subject.append('another').is_a?(Hypostasis::Tuple).must_equal true }
19
+ it { subject.append('another').to_a.must_equal ['tuple', 'example', 123, 'another'] }
20
+
21
+ it { subject.trim.must_equal subject }
22
+ it { subject.trim(1).to_a.must_equal ['tuple', 'example'] }
23
+ it { subject.trim(-1).to_a.must_equal ['example', 123] }
24
+ it { lambda { subject.trim(3) }.must_raise Hypostasis::Errors::TupleExhausted }
25
+ it { lambda { subject.trim(4) }.must_raise Hypostasis::Errors::TupleExhausted }
26
+ it { lambda { subject.trim(-3) }.must_raise Hypostasis::Errors::TupleExhausted }
27
+ it { lambda { subject.trim(-4) }.must_raise Hypostasis::Errors::TupleExhausted }
28
+
29
+ it { lambda { Hypostasis::Tuple.new }.must_raise Hypostasis::Errors::InvalidTuple }
30
+
31
+ it { Hypostasis::Tuple.unpack(subject.to_s).is_a?(Hypostasis::Tuple).must_equal true }
32
+ it { Hypostasis::Tuple.unpack(subject.to_s).to_a.must_equal subject.to_a }
33
+
34
+ it { subject.to_range.must_equal FDB::Tuple.range(['tuple', 'example', 123]) }
35
+ end
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.0.2
4
+ version: 0.0.3
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 00:00:00.000000000 Z
11
+ date: 2014-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fdb
@@ -83,11 +83,21 @@ files:
83
83
  - hypostasis.gemspec
84
84
  - lib/hypostasis.rb
85
85
  - lib/hypostasis/connection.rb
86
+ - lib/hypostasis/data_model/document.rb
87
+ - lib/hypostasis/data_model/key_value.rb
88
+ - lib/hypostasis/data_models.rb
89
+ - lib/hypostasis/errors.rb
90
+ - lib/hypostasis/key_path.rb
86
91
  - lib/hypostasis/namespace.rb
92
+ - lib/hypostasis/tuple.rb
87
93
  - lib/hypostasis/version.rb
88
94
  - test/connection_spec.rb
95
+ - test/data_models/document/document_spec.rb
96
+ - test/data_models/key_value/key_value_spec.rb
97
+ - test/key_path_spec.rb
89
98
  - test/minitest_helper.rb
90
99
  - test/namespace_spec.rb
100
+ - test/tuple_spec.rb
91
101
  homepage: ''
92
102
  licenses:
93
103
  - MIT
@@ -114,5 +124,9 @@ specification_version: 4
114
124
  summary: A layer for FoundationDB providing multiple data models for Ruby.
115
125
  test_files:
116
126
  - test/connection_spec.rb
127
+ - test/data_models/document/document_spec.rb
128
+ - test/data_models/key_value/key_value_spec.rb
129
+ - test/key_path_spec.rb
117
130
  - test/minitest_helper.rb
118
131
  - test/namespace_spec.rb
132
+ - test/tuple_spec.rb