hypostasis 0.3.0 → 0.4.0
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/.travis.yml +7 -22
- data/hypostasis.gemspec +2 -0
- data/lib/hypostasis.rb +8 -0
- data/lib/hypostasis/column_group.rb +9 -8
- data/lib/hypostasis/data_models.rb +2 -0
- data/lib/hypostasis/data_models/column_group.rb +4 -15
- data/lib/hypostasis/data_models/document.rb +14 -0
- data/lib/hypostasis/data_models/for_indexes.rb +12 -0
- data/lib/hypostasis/data_models/utilities.rb +8 -0
- data/lib/hypostasis/document.rb +46 -0
- data/lib/hypostasis/document/findable.rb +48 -0
- data/lib/hypostasis/document/persistence.rb +26 -0
- data/lib/hypostasis/errors.rb +1 -0
- data/lib/hypostasis/ext/bson/date.rb +5 -0
- data/lib/hypostasis/ext/bson/date_time.rb +5 -0
- data/lib/hypostasis/namespace.rb +2 -0
- data/lib/hypostasis/{column_group → shared}/fields.rb +8 -11
- data/lib/hypostasis/shared/indexes.rb +25 -0
- data/lib/hypostasis/shared/namespaced.rb +29 -0
- data/lib/hypostasis/shared/utilities.rb +12 -0
- data/lib/hypostasis/version.rb +1 -1
- data/test/{column_spec.rb → column_group_spec.rb} +0 -0
- data/test/document/indexing_spec.rb +24 -0
- data/test/document_spec.rb +86 -0
- data/test/minitest_helper.rb +19 -9
- data/test/support/indexed_document.rb +12 -0
- data/test/support/sample_document.rb +9 -0
- metadata +67 -23
- data/lib/hypostasis/column_group/indexes.rb +0 -29
- data/lib/hypostasis/column_group/namespaced.rb +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10fcbef73dc4571adad2aff13a7c29c9fd934b09
|
|
4
|
+
data.tar.gz: ff7b955b340befb4abcbde39414873a60af7db22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b8deb5378de71e559c5999e9b4775b8c440b1e6723d3b4f437806971ca47dac622cc04842c723785e1617f13bc274a4c13b125b3169ed26922fb125fd2fa40c
|
|
7
|
+
data.tar.gz: 781f1f1a55419d90c6731d151a62a2fa7f9fb05f7d30420385aba3bb45f4f0d8ecb9ddf659f24f4d5af890304b532b8006442945b585561f5e0086342ddedef4
|
data/.travis.yml
CHANGED
|
@@ -3,49 +3,34 @@ rvm:
|
|
|
3
3
|
- 1.9.3
|
|
4
4
|
- 2.0.0
|
|
5
5
|
- 2.1.0
|
|
6
|
-
# - ruby-head
|
|
7
6
|
- jruby-19mode
|
|
8
|
-
# - jruby-head
|
|
9
7
|
jdk:
|
|
10
8
|
- openjdk6
|
|
11
9
|
- openjdk7
|
|
12
10
|
- oraclejdk7
|
|
13
|
-
|
|
11
|
+
branches:
|
|
12
|
+
only:
|
|
13
|
+
- master
|
|
14
|
+
- /^feature\/.*/
|
|
15
|
+
- /-stable$/
|
|
14
16
|
matrix:
|
|
15
17
|
exclude:
|
|
16
18
|
- rvm: 1.9.3
|
|
17
19
|
jdk: openjdk6
|
|
18
20
|
- rvm: 1.9.3
|
|
19
21
|
jdk: oraclejdk7
|
|
20
|
-
# - rvm: 1.9.3
|
|
21
|
-
# jdk: oraclejdk8
|
|
22
22
|
- rvm: 2.0.0
|
|
23
23
|
jdk: openjdk6
|
|
24
24
|
- rvm: 2.0.0
|
|
25
25
|
jdk: oraclejdk7
|
|
26
|
-
# - rvm: 2.0.0
|
|
27
|
-
# jdk: oraclejdk8
|
|
28
26
|
- rvm: 2.1.0
|
|
29
27
|
jdk: openjdk6
|
|
30
28
|
- rvm: 2.1.0
|
|
31
29
|
jdk: oraclejdk7
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# - rvm: ruby-head
|
|
35
|
-
# jdk: openjdk6
|
|
36
|
-
# - rvm: ruby-head
|
|
37
|
-
# jdk: oraclejdk7
|
|
38
|
-
# - rvm: ruby-head
|
|
39
|
-
# jdk: oraclejdk8
|
|
40
|
-
# allow_failures:
|
|
41
|
-
# - rvm: ruby-head
|
|
42
|
-
# - rvm: jruby-head
|
|
43
|
-
# - jdk: oraclejdk8
|
|
30
|
+
allow_failures:
|
|
31
|
+
- rvm: jruby-19mode
|
|
44
32
|
before_install:
|
|
45
33
|
- wget https://foundationdb.com/downloads/I_accept_the_FoundationDB_Community_License_Agreement/1.0.1/foundationdb-clients_1.0.1-1_amd64.deb
|
|
46
34
|
- wget https://foundationdb.com/downloads/I_accept_the_FoundationDB_Community_License_Agreement/1.0.1/foundationdb-server_1.0.1-1_amd64.deb
|
|
47
35
|
- sudo dpkg -i foundationdb-clients_1.0.1-1_amd64.deb
|
|
48
36
|
- sudo dpkg -i foundationdb-server_1.0.1-1_amd64.deb
|
|
49
|
-
addons:
|
|
50
|
-
code_climate:
|
|
51
|
-
repo_token: 8bd71907fa5f14a405d4adade4ddd62dc4c7d5a2470e025f5c6899fc32ac2898
|
data/hypostasis.gemspec
CHANGED
|
@@ -20,8 +20,10 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
|
|
21
21
|
spec.add_dependency 'fdb', '~> 1.0.1'
|
|
22
22
|
spec.add_dependency 'activesupport', '>= 3.2.0'
|
|
23
|
+
spec.add_dependency 'bson', '~> 2.2'
|
|
23
24
|
|
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
25
26
|
spec.add_development_dependency 'rake'
|
|
26
27
|
spec.add_development_dependency 'minitest', '~> 5.2.0'
|
|
28
|
+
spec.add_development_dependency 'tzinfo'
|
|
27
29
|
end
|
data/lib/hypostasis.rb
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
require 'active_support/inflector'
|
|
3
|
+
require 'bson'
|
|
4
|
+
|
|
5
|
+
require 'hypostasis/ext/bson/date'
|
|
6
|
+
require 'hypostasis/ext/bson/date_time'
|
|
7
|
+
|
|
1
8
|
require 'hypostasis/version'
|
|
2
9
|
|
|
3
10
|
require 'hypostasis/errors'
|
|
@@ -10,3 +17,4 @@ require 'hypostasis/data_models'
|
|
|
10
17
|
require 'hypostasis/namespace'
|
|
11
18
|
|
|
12
19
|
require 'hypostasis/column_group'
|
|
20
|
+
require 'hypostasis/document'
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require '
|
|
1
|
+
require 'hypostasis/shared/utilities'
|
|
2
|
+
require 'hypostasis/shared/namespaced'
|
|
3
|
+
require 'hypostasis/shared/fields'
|
|
4
|
+
require 'hypostasis/shared/indexes'
|
|
3
5
|
|
|
4
|
-
require 'hypostasis/column_group/namespaced'
|
|
5
|
-
require 'hypostasis/column_group/fields'
|
|
6
|
-
require 'hypostasis/column_group/indexes'
|
|
7
6
|
require 'hypostasis/column_group/persistence'
|
|
8
7
|
require 'hypostasis/column_group/findable'
|
|
9
8
|
require 'hypostasis/column_group/belongs_to'
|
|
@@ -13,9 +12,11 @@ require 'hypostasis/column_group/has_many'
|
|
|
13
12
|
module Hypostasis::ColumnGroup
|
|
14
13
|
extend ActiveSupport::Concern
|
|
15
14
|
|
|
16
|
-
include Hypostasis::
|
|
17
|
-
include Hypostasis::
|
|
18
|
-
include Hypostasis::
|
|
15
|
+
include Hypostasis::Shared::Utilities
|
|
16
|
+
include Hypostasis::Shared::Namespaced
|
|
17
|
+
include Hypostasis::Shared::Fields
|
|
18
|
+
include Hypostasis::Shared::Indexes
|
|
19
|
+
|
|
19
20
|
include Hypostasis::ColumnGroup::Persistence
|
|
20
21
|
include Hypostasis::ColumnGroup::Findable
|
|
21
22
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
module Hypostasis::DataModels::ColumnGroup
|
|
2
|
+
include Hypostasis::DataModels::Utilities
|
|
3
|
+
include Hypostasis::DataModels::ForIndexes
|
|
4
|
+
|
|
2
5
|
def transact
|
|
3
6
|
database.transact do |tr|
|
|
4
7
|
yield tr
|
|
@@ -6,24 +9,10 @@ module Hypostasis::DataModels::ColumnGroup
|
|
|
6
9
|
end
|
|
7
10
|
|
|
8
11
|
def for_column_group(column_group, id = nil)
|
|
9
|
-
|
|
10
|
-
document_id = id.nil? ? column_group.id.to_s : id.to_s
|
|
11
|
-
name.to_s + '\\' + Hypostasis::Tuple.new(class_name, document_id).to_s
|
|
12
|
+
name.to_s + '\\' + Hypostasis::Tuple.new(get_class_name(column_group), get_object_id(column_group, id)).to_s
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def for_field(document, field, type)
|
|
15
16
|
for_column_group(document) + '\\' + Hypostasis::Tuple.new(field.to_s, type.to_s).to_s
|
|
16
17
|
end
|
|
17
|
-
|
|
18
|
-
def for_index(document, field_name, value)
|
|
19
|
-
class_name = document.is_a?(Class) ? document.to_s : document.class.to_s
|
|
20
|
-
index_path = Hypostasis::Tuple.new('indexes', class_name).to_s
|
|
21
|
-
value = value.to_s unless value.is_a?(Fixnum) || value.is_a?(Bignum)
|
|
22
|
-
if document.is_a?(Class)
|
|
23
|
-
field_path = Hypostasis::Tuple.new(field_name.to_s, value).to_s
|
|
24
|
-
else
|
|
25
|
-
field_path = Hypostasis::Tuple.new(field_name.to_s, value, document.id.to_s).to_s
|
|
26
|
-
end
|
|
27
|
-
name.to_s + '\\' + index_path + '\\' + field_path
|
|
28
|
-
end
|
|
29
18
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Hypostasis::DataModels::Document
|
|
2
|
+
include Hypostasis::DataModels::Utilities
|
|
3
|
+
include Hypostasis::DataModels::ForIndexes
|
|
4
|
+
|
|
5
|
+
def transact
|
|
6
|
+
database.transact do |tr|
|
|
7
|
+
yield tr
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def for_document(document, id = nil)
|
|
12
|
+
name.to_s + '\\' + Hypostasis::Tuple.new(get_class_name(document), get_object_id(document, id)).to_s
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Hypostasis::DataModels::ForIndexes
|
|
2
|
+
def for_index(object, field_name, value)
|
|
3
|
+
index_path = Hypostasis::Tuple.new('indexes', get_class_name(object)).to_s
|
|
4
|
+
value = value.to_s unless value.is_a?(Fixnum) || value.is_a?(Bignum)
|
|
5
|
+
if object.is_a?(Class)
|
|
6
|
+
field_path = Hypostasis::Tuple.new(field_name.to_s, value).to_s
|
|
7
|
+
else
|
|
8
|
+
field_path = Hypostasis::Tuple.new(field_name.to_s, value, object.id.to_s).to_s
|
|
9
|
+
end
|
|
10
|
+
name.to_s + '\\' + index_path + '\\' + field_path
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
module Hypostasis::DataModels::Utilities
|
|
2
2
|
private
|
|
3
3
|
|
|
4
|
+
def get_class_name(object)
|
|
5
|
+
object.is_a?(Class) ? object.to_s : object.class.to_s
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def get_object_id(object, id = nil)
|
|
9
|
+
id.nil? ? object.id.to_s : id.to_s
|
|
10
|
+
end
|
|
11
|
+
|
|
4
12
|
def reconstitute_value(tuple, raw_value)
|
|
5
13
|
data_type = tuple.to_a.last
|
|
6
14
|
case data_type
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'hypostasis/shared/utilities'
|
|
2
|
+
require 'hypostasis/shared/namespaced'
|
|
3
|
+
require 'hypostasis/shared/fields'
|
|
4
|
+
require 'hypostasis/shared/indexes'
|
|
5
|
+
|
|
6
|
+
require 'hypostasis/document/persistence'
|
|
7
|
+
require 'hypostasis/document/findable'
|
|
8
|
+
|
|
9
|
+
module Hypostasis::Document
|
|
10
|
+
extend ActiveSupport::Concern
|
|
11
|
+
|
|
12
|
+
include Hypostasis::Shared::Utilities
|
|
13
|
+
include Hypostasis::Shared::Namespaced
|
|
14
|
+
include Hypostasis::Shared::Fields
|
|
15
|
+
include Hypostasis::Shared::Indexes
|
|
16
|
+
|
|
17
|
+
include Hypostasis::Document::Persistence
|
|
18
|
+
include Hypostasis::Document::Findable
|
|
19
|
+
|
|
20
|
+
attr_reader :id
|
|
21
|
+
|
|
22
|
+
def initialize(*attributes)
|
|
23
|
+
self.class.namespace.open
|
|
24
|
+
|
|
25
|
+
@fields = {}
|
|
26
|
+
self.class.fields.each {|name| @fields[name] = nil}
|
|
27
|
+
attributes.each {|hsh| hsh.each {|name, value| @fields[name.to_sym] = value}}
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def generate_id
|
|
32
|
+
@id ||= SecureRandom.uuid
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def set_id(id)
|
|
36
|
+
@id ||= id.to_s
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_bson
|
|
40
|
+
@fields.to_bson
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module ClassMethods
|
|
44
|
+
include Hypostasis::DataModels::Utilities
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Hypostasis::Document
|
|
2
|
+
module Findable
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def find(id)
|
|
7
|
+
fdb_key = nil
|
|
8
|
+
namespace.transact do |tr|
|
|
9
|
+
fdb_key = tr.get(namespace.for_document(self, id))
|
|
10
|
+
end
|
|
11
|
+
raise Hypostasis::Errors::DocumentNotFound if fdb_key.nil?
|
|
12
|
+
reconstitute_document(fdb_key.value, id)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def find_where(field_value_pairs)
|
|
16
|
+
results = []
|
|
17
|
+
namespace.transact do |tr|
|
|
18
|
+
field_value_pairs.each do |field, value|
|
|
19
|
+
results << tr.get_range_start_with(namespace.for_index(self, field, value)).to_a
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
results.flatten!
|
|
23
|
+
results.collect! {|result| Hypostasis::Tuple.unpack(result.key.split('\\').last).to_a.last }.compact!
|
|
24
|
+
results.select! {|e| results.count(e) == field_value_pairs.size}
|
|
25
|
+
results.uniq!
|
|
26
|
+
find_many(results)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_many(ids)
|
|
30
|
+
results = []
|
|
31
|
+
namespace.transact do |tr|
|
|
32
|
+
ids.each {|id| results << [tr.get(namespace.for_document(self, id)), id]}
|
|
33
|
+
end
|
|
34
|
+
results.collect! do |result|
|
|
35
|
+
reconstitute_document(result[0], result[1])
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def reconstitute_document(bson_value, id)
|
|
42
|
+
document = self.new(Hash.from_bson(StringIO.new(bson_value)))
|
|
43
|
+
document.set_id(id)
|
|
44
|
+
document
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Hypostasis::Document
|
|
2
|
+
module Persistence
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
def save
|
|
6
|
+
generate_id
|
|
7
|
+
self.class.namespace.transact do |tr|
|
|
8
|
+
tr.set(self.class.namespace.for_document(self), @fields.to_bson)
|
|
9
|
+
indexed_fields_to_commit.each {|key| tr.set(key, 'true') }
|
|
10
|
+
end
|
|
11
|
+
self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def destroy
|
|
15
|
+
self.class.namespace.transact do |tr|
|
|
16
|
+
tr.clear_range_start_with(self.class.namespace.for_document(self))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module ClassMethods
|
|
21
|
+
def create(*attributes)
|
|
22
|
+
self.new(*attributes).save
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/hypostasis/errors.rb
CHANGED
data/lib/hypostasis/namespace.rb
CHANGED
|
@@ -58,6 +58,8 @@ private
|
|
|
58
58
|
self.extend Hypostasis::DataModels::KeyValue
|
|
59
59
|
when :column_group
|
|
60
60
|
self.extend Hypostasis::DataModels::ColumnGroup
|
|
61
|
+
when :document
|
|
62
|
+
self.extend Hypostasis::DataModels::Document
|
|
61
63
|
else
|
|
62
64
|
raise Hypostasis::Errors::UnknownNamespaceDataModel, "#{@data_model} unknown"
|
|
63
65
|
end
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
module Hypostasis::
|
|
1
|
+
module Hypostasis::Shared
|
|
2
2
|
module Fields
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
|
+
included do
|
|
6
|
+
cattr_accessor_with_default :fields, []
|
|
7
|
+
end
|
|
8
|
+
|
|
5
9
|
module ClassMethods
|
|
6
10
|
def field(name, options = {})
|
|
7
11
|
register_field(name.to_sym)
|
|
8
12
|
create_accessors(name.to_s, options)
|
|
9
13
|
end
|
|
10
14
|
|
|
11
|
-
def fields
|
|
12
|
-
self.class_eval { class_variable_get(:@@fields) }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
15
|
private
|
|
16
16
|
|
|
17
17
|
def register_field(name)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
registered_fields << name.to_sym
|
|
22
|
-
class_variable_set(:@@fields, registered_fields)
|
|
23
|
-
end
|
|
18
|
+
registered_fields = fields
|
|
19
|
+
registered_fields << name.to_sym
|
|
20
|
+
fields = registered_fields
|
|
24
21
|
end
|
|
25
22
|
|
|
26
23
|
def create_accessors(name, options)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Hypostasis::Shared
|
|
2
|
+
module Indexes
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
cattr_accessor_with_default :indexed_fields, []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def indexed_fields_to_commit
|
|
12
|
+
indexed_fields.collect do |field_name|
|
|
13
|
+
self.class.namespace.for_index(self, field_name, @fields[field_name])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module ClassMethods
|
|
18
|
+
def index(field_name, options = {})
|
|
19
|
+
registered_indexed_fields = indexed_fields
|
|
20
|
+
registered_indexed_fields << field_name.to_sym
|
|
21
|
+
indexed_fields = registered_indexed_fields
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Hypostasis::Shared
|
|
2
|
+
module Namespaced
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def use_namespace(namespace)
|
|
7
|
+
self.class_eval do
|
|
8
|
+
class_variable_set(:@@namespace, Hypostasis::Namespace.new(namespace.to_s, detect_data_model))
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def namespace
|
|
13
|
+
self.class_eval { class_variable_get(:@@namespace) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def detect_data_model
|
|
19
|
+
if self.included_modules.include?(Hypostasis::ColumnGroup)
|
|
20
|
+
:column_group
|
|
21
|
+
elsif self.included_modules.include?(Hypostasis::Document)
|
|
22
|
+
:document
|
|
23
|
+
else
|
|
24
|
+
:key_value
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Hypostasis::Shared
|
|
2
|
+
module Utilities
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def cattr_accessor_with_default(name, default = nil)
|
|
7
|
+
cattr_accessor name
|
|
8
|
+
class_variable_set("@@#{name.to_s}".to_sym, default)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/hypostasis/version.rb
CHANGED
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'minitest_helper'
|
|
2
|
+
|
|
3
|
+
describe 'Hypostasis::Document indexing' do
|
|
4
|
+
before do
|
|
5
|
+
Hypostasis::Connection.create_namespace 'indexed_documents', data_model: :document
|
|
6
|
+
|
|
7
|
+
IndexedDocument.create(name: 'John', age: 21, dob: Date.today.prev_year(21))
|
|
8
|
+
IndexedDocument.create(name: 'Jane', age: 21, dob: Date.today.prev_year(21))
|
|
9
|
+
IndexedDocument.create(name: 'John', age: 23, dob: Date.today.prev_year(23))
|
|
10
|
+
IndexedDocument.create(name: 'Tom', age: 20, dob: Date.today.prev_year(20))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
after do
|
|
14
|
+
Hypostasis::Connection.destroy_namespace 'indexed_documents'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it { database.get_range_start_with(index_path(IndexedDocument, :name)).size.must_equal 4 }
|
|
18
|
+
it { database.get_range_start_with(index_path(IndexedDocument, :age)).size.must_equal 4 }
|
|
19
|
+
|
|
20
|
+
it { database.get_range_start_with(index_path(IndexedDocument, :name, 'John')).size.must_equal 2 }
|
|
21
|
+
it { database.get_range_start_with(index_path(IndexedDocument, :name, 'Jane')).size.must_equal 1 }
|
|
22
|
+
|
|
23
|
+
it { database.get_range_start_with(index_path(IndexedDocument, :age, 21)).size.must_equal 2 }
|
|
24
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
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_documents', data_model: :document
|
|
8
|
+
Hypostasis::Connection.create_namespace 'indexed_documents', data_model: :document
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after do
|
|
12
|
+
Hypostasis::Connection.destroy_namespace 'sample_documents'
|
|
13
|
+
Hypostasis::Connection.destroy_namespace 'indexed_documents'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it { subject.must_respond_to :name }
|
|
17
|
+
it { subject.must_respond_to :age }
|
|
18
|
+
it { subject.must_respond_to :dob }
|
|
19
|
+
|
|
20
|
+
it { subject.must_respond_to :name= }
|
|
21
|
+
it { subject.must_respond_to :age= }
|
|
22
|
+
it { subject.must_respond_to :dob= }
|
|
23
|
+
|
|
24
|
+
it { subject.name.must_equal 'John' }
|
|
25
|
+
it { subject.age.must_equal 21 }
|
|
26
|
+
it { subject.dob.must_equal Date.today.prev_year(21) }
|
|
27
|
+
|
|
28
|
+
it { subject.must_respond_to :save }
|
|
29
|
+
|
|
30
|
+
describe '.create' do
|
|
31
|
+
let(:subject) { SampleDocument.create(name: 'John', age: 21, dob: Date.today.prev_year(21)) }
|
|
32
|
+
|
|
33
|
+
after do
|
|
34
|
+
subject.destroy
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it { subject.id.wont_be_nil }
|
|
38
|
+
it { database.get(document_path(subject)).must_equal subject.to_bson }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '.save' do
|
|
42
|
+
before do
|
|
43
|
+
subject.save
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
after do
|
|
47
|
+
subject.destroy
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it { subject.id.wont_be_nil }
|
|
51
|
+
it { database.get(document_path(subject)).must_equal subject.to_bson }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe '.find' do
|
|
55
|
+
let(:document_id) { subject.save.id }
|
|
56
|
+
let(:found) { SampleDocument.find(document_id) }
|
|
57
|
+
|
|
58
|
+
after do
|
|
59
|
+
subject.destroy
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it { found.is_a?(SampleDocument).must_equal true }
|
|
63
|
+
it { found.id.must_equal document_id }
|
|
64
|
+
|
|
65
|
+
it { found.name.must_equal 'John' }
|
|
66
|
+
it { found.age.must_equal 21 }
|
|
67
|
+
it { found.dob.must_equal Date.today.prev_year(21).at_midnight.to_time }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe '.find_where' do
|
|
71
|
+
before do
|
|
72
|
+
IndexedDocument.create(name: 'John', age: 21, dob: Date.today.prev_year(21))
|
|
73
|
+
IndexedDocument.create(name: 'Jane', age: 21, dob: Date.today.prev_year(21))
|
|
74
|
+
IndexedDocument.create(name: 'John', age: 23, dob: Date.today.prev_year(23))
|
|
75
|
+
IndexedDocument.create(name: 'Tom', age: 20, dob: Date.today.prev_year(20))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it { IndexedDocument.find_where(name: 'John').size.must_equal 2 }
|
|
79
|
+
it { IndexedDocument.find_where(age: 21).size.must_equal 2 }
|
|
80
|
+
it { IndexedDocument.find_where(name: 'Tom').size.must_equal 1 }
|
|
81
|
+
it { IndexedDocument.find_where(name: 'Tom').first.is_a?(IndexedDocument).must_equal true }
|
|
82
|
+
|
|
83
|
+
it { IndexedDocument.find_where(name: 'John', age: 23).size.must_equal 1 }
|
|
84
|
+
it { IndexedDocument.find_where(name: 'John', age: 23).first.is_a?(IndexedDocument).must_equal true }
|
|
85
|
+
end
|
|
86
|
+
end
|
data/test/minitest_helper.rb
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
require 'codeclimate-test-reporter'
|
|
3
|
-
CodeClimate::TestReporter.start
|
|
4
|
-
else
|
|
1
|
+
unless ENV['CI']
|
|
5
2
|
require 'simplecov'
|
|
6
3
|
SimpleCov.start do
|
|
7
4
|
add_filter '/test/'
|
|
@@ -11,10 +8,17 @@ end
|
|
|
11
8
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
12
9
|
require 'hypostasis'
|
|
13
10
|
|
|
11
|
+
require 'active_support/core_ext'
|
|
12
|
+
require 'active_support/time_with_zone'
|
|
13
|
+
|
|
14
14
|
require 'minitest/autorun'
|
|
15
15
|
|
|
16
16
|
require 'support/sample_column'
|
|
17
17
|
require 'support/indexed_column'
|
|
18
|
+
require 'support/sample_document'
|
|
19
|
+
require 'support/indexed_document'
|
|
20
|
+
|
|
21
|
+
Time.zone = 'UTC'
|
|
18
22
|
|
|
19
23
|
class Minitest::Spec
|
|
20
24
|
|
|
@@ -22,17 +26,23 @@ class Minitest::Spec
|
|
|
22
26
|
@database ||= FDB.open
|
|
23
27
|
end
|
|
24
28
|
|
|
25
|
-
def
|
|
29
|
+
def document_path(document)
|
|
26
30
|
document_namespace = document.class.namespace.to_s
|
|
27
31
|
document_tuple = Hypostasis::Tuple.new(document.class.to_s, document.id.to_s).to_s
|
|
28
32
|
document_namespace + '\\' + document_tuple
|
|
29
33
|
end
|
|
30
34
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
def column_path(column_group)
|
|
36
|
+
column_namespace = column_group.class.namespace.to_s
|
|
37
|
+
column_tuple = Hypostasis::Tuple.new(column_group.class.to_s, column_group.id.to_s).to_s
|
|
38
|
+
column_namespace + '\\' + column_tuple
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def field_path(column_group, name, type)
|
|
42
|
+
column_namespace = column_group.class.namespace.to_s
|
|
43
|
+
column_tuple = Hypostasis::Tuple.new(column_group.class.to_s, column_group.id.to_s).to_s
|
|
34
44
|
field_tuple = Hypostasis::Tuple.new(name.to_s, type.to_s).to_s
|
|
35
|
-
|
|
45
|
+
column_namespace + '\\' + column_tuple + '\\' + field_tuple
|
|
36
46
|
end
|
|
37
47
|
|
|
38
48
|
def index_path(klass, field_name, value = nil)
|
metadata
CHANGED
|
@@ -1,85 +1,113 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hypostasis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
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-
|
|
11
|
+
date: 2014-02-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: fdb
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ~>
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: 1.0.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - ~>
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: 1.0.1
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: activesupport
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- -
|
|
31
|
+
- - '>='
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: 3.2.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- -
|
|
38
|
+
- - '>='
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: 3.2.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bson
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ~>
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '2.2'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ~>
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '2.2'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: bundler
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
44
58
|
requirements:
|
|
45
|
-
- -
|
|
59
|
+
- - ~>
|
|
46
60
|
- !ruby/object:Gem::Version
|
|
47
61
|
version: '1.3'
|
|
48
62
|
type: :development
|
|
49
63
|
prerelease: false
|
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
65
|
requirements:
|
|
52
|
-
- -
|
|
66
|
+
- - ~>
|
|
53
67
|
- !ruby/object:Gem::Version
|
|
54
68
|
version: '1.3'
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
70
|
name: rake
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
58
72
|
requirements:
|
|
59
|
-
- -
|
|
73
|
+
- - '>='
|
|
60
74
|
- !ruby/object:Gem::Version
|
|
61
75
|
version: '0'
|
|
62
76
|
type: :development
|
|
63
77
|
prerelease: false
|
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
79
|
requirements:
|
|
66
|
-
- -
|
|
80
|
+
- - '>='
|
|
67
81
|
- !ruby/object:Gem::Version
|
|
68
82
|
version: '0'
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
84
|
name: minitest
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
72
86
|
requirements:
|
|
73
|
-
- -
|
|
87
|
+
- - ~>
|
|
74
88
|
- !ruby/object:Gem::Version
|
|
75
89
|
version: 5.2.0
|
|
76
90
|
type: :development
|
|
77
91
|
prerelease: false
|
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
93
|
requirements:
|
|
80
|
-
- -
|
|
94
|
+
- - ~>
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
96
|
version: 5.2.0
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: tzinfo
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - '>='
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - '>='
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
83
111
|
description: A layer for FoundationDB providing multiple data models for Ruby.
|
|
84
112
|
email:
|
|
85
113
|
- james@plainprograms.com
|
|
@@ -87,9 +115,9 @@ executables: []
|
|
|
87
115
|
extensions: []
|
|
88
116
|
extra_rdoc_files: []
|
|
89
117
|
files:
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
118
|
+
- .gitignore
|
|
119
|
+
- .ruby-version
|
|
120
|
+
- .travis.yml
|
|
93
121
|
- Gemfile
|
|
94
122
|
- LICENSE.txt
|
|
95
123
|
- README.md
|
|
@@ -99,35 +127,47 @@ files:
|
|
|
99
127
|
- lib/hypostasis.rb
|
|
100
128
|
- lib/hypostasis/column_group.rb
|
|
101
129
|
- lib/hypostasis/column_group/belongs_to.rb
|
|
102
|
-
- lib/hypostasis/column_group/fields.rb
|
|
103
130
|
- lib/hypostasis/column_group/findable.rb
|
|
104
131
|
- lib/hypostasis/column_group/has_many.rb
|
|
105
132
|
- lib/hypostasis/column_group/has_one.rb
|
|
106
|
-
- lib/hypostasis/column_group/indexes.rb
|
|
107
|
-
- lib/hypostasis/column_group/namespaced.rb
|
|
108
133
|
- lib/hypostasis/column_group/persistence.rb
|
|
109
134
|
- lib/hypostasis/connection.rb
|
|
110
135
|
- lib/hypostasis/data_models.rb
|
|
111
136
|
- lib/hypostasis/data_models/column_group.rb
|
|
137
|
+
- lib/hypostasis/data_models/document.rb
|
|
138
|
+
- lib/hypostasis/data_models/for_indexes.rb
|
|
112
139
|
- lib/hypostasis/data_models/key_value.rb
|
|
113
140
|
- lib/hypostasis/data_models/utilities.rb
|
|
141
|
+
- lib/hypostasis/document.rb
|
|
142
|
+
- lib/hypostasis/document/findable.rb
|
|
143
|
+
- lib/hypostasis/document/persistence.rb
|
|
114
144
|
- lib/hypostasis/errors.rb
|
|
145
|
+
- lib/hypostasis/ext/bson/date.rb
|
|
146
|
+
- lib/hypostasis/ext/bson/date_time.rb
|
|
115
147
|
- lib/hypostasis/key.rb
|
|
116
148
|
- lib/hypostasis/key_path.rb
|
|
117
149
|
- lib/hypostasis/namespace.rb
|
|
150
|
+
- lib/hypostasis/shared/fields.rb
|
|
151
|
+
- lib/hypostasis/shared/indexes.rb
|
|
152
|
+
- lib/hypostasis/shared/namespaced.rb
|
|
153
|
+
- lib/hypostasis/shared/utilities.rb
|
|
118
154
|
- lib/hypostasis/tuple.rb
|
|
119
155
|
- lib/hypostasis/version.rb
|
|
120
156
|
- provision.sh
|
|
121
157
|
- test/column/has_many_spec.rb
|
|
122
158
|
- test/column/has_one_spec.rb
|
|
123
|
-
- test/
|
|
159
|
+
- test/column_group_spec.rb
|
|
124
160
|
- test/connection_spec.rb
|
|
161
|
+
- test/document/indexing_spec.rb
|
|
162
|
+
- test/document_spec.rb
|
|
125
163
|
- test/key_path_spec.rb
|
|
126
164
|
- test/key_spec.rb
|
|
127
165
|
- test/minitest_helper.rb
|
|
128
166
|
- test/namespace_spec.rb
|
|
129
167
|
- test/support/indexed_column.rb
|
|
168
|
+
- test/support/indexed_document.rb
|
|
130
169
|
- test/support/sample_column.rb
|
|
170
|
+
- test/support/sample_document.rb
|
|
131
171
|
- test/tuple_spec.rb
|
|
132
172
|
homepage: ''
|
|
133
173
|
licenses:
|
|
@@ -139,29 +179,33 @@ require_paths:
|
|
|
139
179
|
- lib
|
|
140
180
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
181
|
requirements:
|
|
142
|
-
- -
|
|
182
|
+
- - '>='
|
|
143
183
|
- !ruby/object:Gem::Version
|
|
144
184
|
version: '0'
|
|
145
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
186
|
requirements:
|
|
147
|
-
- -
|
|
187
|
+
- - '>='
|
|
148
188
|
- !ruby/object:Gem::Version
|
|
149
189
|
version: '0'
|
|
150
190
|
requirements: []
|
|
151
191
|
rubyforge_project:
|
|
152
|
-
rubygems_version: 2.
|
|
192
|
+
rubygems_version: 2.1.11
|
|
153
193
|
signing_key:
|
|
154
194
|
specification_version: 4
|
|
155
195
|
summary: A layer for FoundationDB providing multiple data models for Ruby.
|
|
156
196
|
test_files:
|
|
157
197
|
- test/column/has_many_spec.rb
|
|
158
198
|
- test/column/has_one_spec.rb
|
|
159
|
-
- test/
|
|
199
|
+
- test/column_group_spec.rb
|
|
160
200
|
- test/connection_spec.rb
|
|
201
|
+
- test/document/indexing_spec.rb
|
|
202
|
+
- test/document_spec.rb
|
|
161
203
|
- test/key_path_spec.rb
|
|
162
204
|
- test/key_spec.rb
|
|
163
205
|
- test/minitest_helper.rb
|
|
164
206
|
- test/namespace_spec.rb
|
|
165
207
|
- test/support/indexed_column.rb
|
|
208
|
+
- test/support/indexed_document.rb
|
|
166
209
|
- test/support/sample_column.rb
|
|
210
|
+
- test/support/sample_document.rb
|
|
167
211
|
- test/tuple_spec.rb
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module Hypostasis::ColumnGroup
|
|
2
|
-
module Indexes
|
|
3
|
-
extend ActiveSupport::Concern
|
|
4
|
-
|
|
5
|
-
private
|
|
6
|
-
|
|
7
|
-
def indexed_fields_to_commit
|
|
8
|
-
self.class.class_eval { class_variable_set(:@@indexed_fields, []) unless class_variable_defined?(:@@indexed_fields) }
|
|
9
|
-
self.class.indexed_fields.collect do |field_name|
|
|
10
|
-
self.class.namespace.for_index(self, field_name, @fields[field_name])
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
module ClassMethods
|
|
15
|
-
def index(field_name, options = {})
|
|
16
|
-
self.class_eval do
|
|
17
|
-
class_variable_set(:@@indexed_fields, []) unless class_variable_defined?(:@@indexed_fields)
|
|
18
|
-
registered_indexed_fields = class_variable_get(:@@indexed_fields)
|
|
19
|
-
registered_indexed_fields << field_name.to_sym
|
|
20
|
-
class_variable_set(:@@indexed_fields, registered_indexed_fields)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def indexed_fields
|
|
25
|
-
self.class_eval { class_variable_get(:@@indexed_fields) }
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module Hypostasis::ColumnGroup
|
|
2
|
-
module Namespaced
|
|
3
|
-
extend ActiveSupport::Concern
|
|
4
|
-
|
|
5
|
-
module ClassMethods
|
|
6
|
-
def use_namespace(namespace)
|
|
7
|
-
data_model = :key_value
|
|
8
|
-
data_model = :column_group if self.included_modules.include?(Hypostasis::ColumnGroup)
|
|
9
|
-
self.class_eval do
|
|
10
|
-
class_variable_set(:@@namespace, Hypostasis::Namespace.new(namespace.to_s, data_model))
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def namespace
|
|
15
|
-
self.class_eval { class_variable_get(:@@namespace) }
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|