hypostasis 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|