hypostasis 0.2.1 → 0.2.2

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: 1c80aa68763652e26b5530ce3a5edae29146fe5b
4
- data.tar.gz: 67ea0fe2e5b19379894a8ac743e9d8e3d5d4bb3c
3
+ metadata.gz: 2e9fbd57ef0554f4b251ba9e9f0a93bfe87e06b5
4
+ data.tar.gz: e8b6b94f4a7dc94715f3738c6cb84083731b2d79
5
5
  SHA512:
6
- metadata.gz: 5032721bdb5e7077d73150fab9c93c8a81a4c2b31ebe5d94ad3551b0628d5c2e814e24dff04dab9f6fcd378ff76a783614b2b7f0af0b8797b628f595a393d8f1
7
- data.tar.gz: 81b5fdc2b7ad080af654c889be5956ad48e7e5dbcb2a833e29bdb797439b00643de14582d1fbd8e5d145204b32a780a58098b077eaaa3e311ab4b6630c5af0fb
6
+ metadata.gz: 7063a5209d6b7e529314c3918474a05b289e19bee7f0801468c9793e5ebb68605ce37b304cf94fa67f3056ca9bcaa97b078b6e5dd4d8f43f725d8b24d4b456d5
7
+ data.tar.gz: c328c728d3f64e507cbba577350b1a294555e41bc647154b24a2de60c4636eb8f59deeb091c21807219495a298c20f453dca2542c80a6a9edf7a64ca1494f726
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.0.0
1
+ ruby
data/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/hypostasis.png)](http://badge.fury.io/rb/hypostasis)
4
4
  [![Build Status](https://travis-ci.org/hypostasis/hypostasis.png)](https://travis-ci.org/hypostasis/hypostasis)
5
- [![Coverate](https://codeclimate.com/repos/52d192fa6956802453000df7/badges/0e37d2069e868f797adc/coverage.png)](https://codeclimate.com/repos/52d192fa6956802453000df7/feed)
6
- [![Code Climate](https://codeclimate.com/repos/52d192fa6956802453000df7/badges/0e37d2069e868f797adc/gpa.png)](https://codeclimate.com/repos/52d192fa6956802453000df7/feed)
5
+ [![Code Climate](https://codeclimate.com/github/hypostasis/hypostasis.png)](https://codeclimate.com/github/hypostasis/hypostasis)
7
6
  [![Dependency Status](https://gemnasium.com/hypostasis/hypostasis.png)](https://gemnasium.com/hypostasis/hypostasis)
8
7
 
9
8
  Hypostasis is a layer for FoundationDB that supports multiple data models on
@@ -20,12 +19,8 @@ variety of data models while using the same underlying storage system, provided
20
19
  by FoundationDB. The data models Hypostasis currently aims to support are the
21
20
  following:
22
21
 
23
- * Document-Oriented
24
- * Simple Key-Value (Wrapper for naked FoundationDB)
25
- * Relational (an RDBMS without SQL)
26
- * Column-Oriented (like Cassandra without CQL)
27
-
28
- The initial focus will be on the Document-Oriented and simple Key-Value models.
22
+ * Document
23
+ * Key-Value
29
24
 
30
25
  ## Installation
31
26
 
@@ -43,10 +38,10 @@ Or install it yourself as:
43
38
 
44
39
  ## Usage
45
40
 
46
- Hypostasis is still very much Alpha quality software, only suitable for
47
- experimentation. But, feel free to play around with it. Documentation will be
48
- written to define how to use the various data models provided by Hypostasis as
49
- the project matures and the APIs stabilize.
41
+ Hypostasis is beta quality software, please keep this in mind. Until the first
42
+ major version is released the API is not to be considered stable. Feel free to
43
+ play around with it and open issues for anything you find that causes a problem
44
+ or for any features you want to see added.
50
45
 
51
46
  Until then, we suggest reading the code and the tests.
52
47
 
@@ -73,6 +68,44 @@ basic language types currently suported include the following:
73
68
  * Time
74
69
  * Boolean
75
70
 
71
+ ### Document Data Model
72
+
73
+ require 'hypostasis'
74
+
75
+ ns = Hypostasis::Connection.create_namespace('keystore', {data_model: :document})
76
+
77
+ class SampleDocument
78
+ include Hypostasis::Document
79
+
80
+ field :name
81
+ field :age
82
+ field :dob
83
+
84
+ index :name
85
+ index :age
86
+ end
87
+
88
+ SampleDocument.create(name: 'John', age: 21, dob: Date.today.prev_year(21))
89
+
90
+ SampleDocument.find(<<id>>)
91
+
92
+ SampleDocument.find_where(name: 'John')
93
+ SampleDocument.find_where(age: 21)
94
+
95
+ The Document data model provides a simple document-oriented data model on top
96
+ of FoundationDB, including simple indexing. Like the Key-Value data model the
97
+ document-oriented model is able to automatically encode and reconstitute
98
+ certain basic Ruby data types, including the following:
99
+
100
+ * String
101
+ * Fixnum
102
+ * Bignum
103
+ * Float
104
+ * Date
105
+ * DateTime
106
+ * Time
107
+ * Boolean
108
+
76
109
  ## Contributing
77
110
 
78
111
  1. Fork it
data/Rakefile CHANGED
@@ -7,4 +7,13 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.verbose = true
8
8
  end
9
9
 
10
- task :default => :test
10
+ if system('vagrant --version > /dev/null 2>&1') && system('vagrant exec -h > /dev/null 2>&1')
11
+ desc 'Run tests within Vagrant'
12
+ task :vagrant_test do
13
+ system 'vagrant exec rake test'
14
+ end
15
+
16
+ task :default => :vagrant_test
17
+ else
18
+ task :default => :test
19
+ end
data/Vagrantfile ADDED
@@ -0,0 +1,22 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure('2') do |config|
5
+ config.vm.box = 'precise64'
6
+
7
+ config.vm.provider :virtualbox do |vb|
8
+ vb.box_url = 'http://files.vagrantup.com/precise64.box'
9
+ vb.memory = 4096
10
+ end
11
+
12
+ config.vm.provider :vmware_fusion do |vw|
13
+ vw.box = 'precise64_vmware'
14
+ vw.box_url = 'http://files.vagrantup.com/precise64_vmware.box'
15
+ vw.memory = 4096
16
+ end
17
+
18
+ config.vm.provision 'shell', path: 'provision.sh'
19
+
20
+ config.exec.root = '/vagrant'
21
+ config.exec.prepend_with 'bundle exec'
22
+ end
@@ -20,6 +20,8 @@ module Hypostasis::DataModels::Utilities
20
20
  true
21
21
  when 'FalseClass'
22
22
  false
23
+ when 'NilClass'
24
+ nil
23
25
  else
24
26
  raise Hypostasis::Errors::UnknownValueType
25
27
  end
@@ -0,0 +1,18 @@
1
+ module Hypostasis::Document
2
+ module BelongsTo
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def belongs_to(klass)
7
+ field_name = "#{klass.to_s}_id"
8
+ accessor_name = klass.to_s
9
+ parent_klass = klass.to_s.classify
10
+ self.class_eval do
11
+ field field_name.to_sym
12
+ index field_name.to_sym
13
+ define_method(accessor_name) { parent_klass.constantize.find(self.send(field_name.to_sym)) }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -9,12 +9,16 @@ module Hypostasis::Document
9
9
  end
10
10
 
11
11
  def fields
12
- @@fields
12
+ self.class_eval { class_variable_get(:@@fields) }
13
13
  end
14
14
 
15
15
  def register_field(name)
16
- @@fields = [] unless defined?(@@fields)
17
- @@fields << name.to_sym
16
+ self.class_eval do
17
+ class_variable_set(:@@fields, []) unless class_variable_defined?(:@@fields)
18
+ registered_fields = class_variable_get(:@@fields)
19
+ registered_fields << name.to_sym
20
+ class_variable_set(:@@fields, registered_fields)
21
+ end
18
22
  end
19
23
 
20
24
  def create_accessors(name, options)
@@ -6,9 +6,9 @@ module Hypostasis::Document
6
6
  def find(id)
7
7
  document_keys = []
8
8
  namespace.transact do |tr|
9
- document_keys = tr.get_range_start_with(namespace.for_document(self, id))
9
+ document_keys = tr.get_range_start_with(namespace.for_document(self, id)).to_a
10
10
  end
11
- #raise Hypostasis::Errors::DocumentNotFound if document_keys.empty?
11
+ raise Hypostasis::Errors::DocumentNotFound if document_keys.empty?
12
12
  attributes = {}
13
13
  id = Hypostasis::Tuple.unpack(document_keys.first.key.split('\\')[1]).to_a[1]
14
14
  document_keys.each do |key|
@@ -0,0 +1,16 @@
1
+ module Hypostasis::Document
2
+ module HasOne
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def has_one(klass)
7
+ accessor_name = klass.to_s
8
+ child_klass = klass.to_s.classify
9
+ self_klass = "#{self.to_s.underscore}_id".to_sym
10
+ self.class_eval do
11
+ define_method(accessor_name) { child_klass.constantize.find_where(self_klass => @id).first }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -3,6 +3,7 @@ module Hypostasis::Document
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def indexed_fields_to_commit
6
+ self.class.class_eval { class_variable_set(:@@indexed_fields, []) unless class_variable_defined?(:@@indexed_fields) }
6
7
  self.class.indexed_fields.collect do |field_name|
7
8
  self.class.namespace.for_index(self, field_name, @fields[field_name])
8
9
  end
@@ -10,12 +11,16 @@ module Hypostasis::Document
10
11
 
11
12
  module ClassMethods
12
13
  def index(field_name, options = {})
13
- @@indexed_fields = [] unless defined? @@indexed_fields
14
- @@indexed_fields << field_name.to_sym
14
+ self.class_eval do
15
+ class_variable_set(:@@indexed_fields, []) unless class_variable_defined?(:@@indexed_fields)
16
+ registered_indexed_fields = class_variable_get(:@@indexed_fields)
17
+ registered_indexed_fields << field_name.to_sym
18
+ class_variable_set(:@@indexed_fields, registered_indexed_fields)
19
+ end
15
20
  end
16
21
 
17
22
  def indexed_fields
18
- @@indexed_fields
23
+ self.class_eval { class_variable_get(:@@indexed_fields) }
19
24
  end
20
25
  end
21
26
  end
@@ -0,0 +1,19 @@
1
+ module Hypostasis::Document
2
+ module Namespaced
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def use_namespace(namespace)
7
+ data_model = :key_value
8
+ data_model = :document if self.included_modules.include?(Hypostasis::Document)
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
@@ -1,18 +1,26 @@
1
1
  require 'active_support/concern'
2
+ require 'active_support/inflector'
2
3
 
4
+ require 'hypostasis/document/namespaced'
3
5
  require 'hypostasis/document/fields'
4
6
  require 'hypostasis/document/indexes'
5
7
  require 'hypostasis/document/persistence'
6
8
  require 'hypostasis/document/findable'
9
+ require 'hypostasis/document/belongs_to'
10
+ require 'hypostasis/document/has_one'
7
11
 
8
12
  module Hypostasis::Document
9
13
  extend ActiveSupport::Concern
10
14
 
15
+ include Hypostasis::Document::Namespaced
11
16
  include Hypostasis::Document::Fields
12
17
  include Hypostasis::Document::Indexes
13
18
  include Hypostasis::Document::Persistence
14
19
  include Hypostasis::Document::Findable
15
20
 
21
+ include Hypostasis::Document::BelongsTo
22
+ include Hypostasis::Document::HasOne
23
+
16
24
  attr_reader :id
17
25
 
18
26
  def initialize(*attributes)
@@ -21,6 +29,7 @@ module Hypostasis::Document
21
29
  @fields = {}
22
30
  self.class.fields.each {|name| @fields[name] = nil}
23
31
  attributes.each {|hsh| hsh.each {|name, value| @fields[name.to_sym] = value}}
32
+ self
24
33
  end
25
34
 
26
35
  def generate_id
@@ -33,17 +42,5 @@ module Hypostasis::Document
33
42
 
34
43
  module ClassMethods
35
44
  include Hypostasis::DataModels::Utilities
36
-
37
- def use_namespace(namespace)
38
- @@namespace = Hypostasis::Namespace.new(namespace.to_s, :document)
39
- end
40
-
41
- def namespace
42
- @@namespace
43
- end
44
-
45
- def supported_field_types
46
- @@supported_field_types ||= %w{Fixnum Bignum String Integer Float Date DateTime Time Boolean}
47
- end
48
45
  end
49
46
  end
@@ -10,4 +10,5 @@ module Hypostasis::Errors
10
10
  class TupleExhausted < StandardError; end
11
11
  class UnknownValueType < StandardError; end
12
12
  class MustDefineFieldType < StandardError; end
13
+ class DocumentNotFound < StandardError; end
13
14
  end
@@ -1,3 +1,3 @@
1
1
  module Hypostasis
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
data/provision.sh ADDED
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+
3
+ apt-get -y install curl git
4
+
5
+ wget https://foundationdb.com/downloads/I_accept_the_FoundationDB_Community_License_Agreement/1.0.1/foundationdb-clients_1.0.1-1_amd64.deb
6
+ wget https://foundationdb.com/downloads/I_accept_the_FoundationDB_Community_License_Agreement/1.0.1/foundationdb-server_1.0.1-1_amd64.deb
7
+
8
+ sudo dpkg -i foundationdb-clients_1.0.1-1_amd64.deb foundationdb-server_1.0.1-1_amd64.deb
9
+
10
+ sudo su - vagrant
11
+ cd /home/vagrant
12
+ \curl -sSL https://get.rvm.io | bash -s stable --ruby --gems=fdb
13
+ source /usr/local/rvm/scripts/rvm
14
+
15
+ cd /vagrant; bundle
@@ -0,0 +1,44 @@
1
+ require 'minitest_helper'
2
+
3
+ class HasOneOwnerDocument
4
+ include Hypostasis::Document
5
+
6
+ use_namespace 'hasone_docs'
7
+
8
+ field :name
9
+ field :age
10
+
11
+ has_one :has_one_child_document
12
+ end
13
+
14
+ class HasOneChildDocument
15
+ include Hypostasis::Document
16
+
17
+ use_namespace 'hasone_docs'
18
+
19
+ field :name
20
+ field :age
21
+
22
+ belongs_to :has_one_owner_document
23
+ end
24
+
25
+ describe 'Document has_one Relationship' do
26
+ before do
27
+ Hypostasis::Connection.create_namespace 'hasone_docs', data_model: :document
28
+ @owner = HasOneOwnerDocument.create(name: 'John', age: '25')
29
+ @child = HasOneChildDocument.create(name: 'James', age: '6', has_one_owner_document_id: @owner.id)
30
+ end
31
+
32
+ after do
33
+ Hypostasis::Connection.destroy_namespace 'hasone_docs'
34
+ end
35
+
36
+ it { @owner.must_respond_to :has_one_child_document }
37
+ it { @child.must_respond_to :has_one_owner_document }
38
+
39
+ it { @owner.has_one_child_document.is_a?(HasOneChildDocument).must_equal true }
40
+ it { @owner.has_one_child_document.id.must_equal @child.id }
41
+
42
+ it { @child.has_one_owner_document.is_a?(HasOneOwnerDocument).must_equal true }
43
+ it { @child.has_one_owner_document.id.must_equal @owner.id }
44
+ end
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hypostasis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
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-25 00:00:00.000000000 Z
11
+ date: 2014-01-28 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
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: 5.2.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 5.2.0
83
83
  description: A layer for FoundationDB providing multiple data models for Ruby.
@@ -87,13 +87,14 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
- - .gitignore
91
- - .ruby-version
92
- - .travis.yml
90
+ - ".gitignore"
91
+ - ".ruby-version"
92
+ - ".travis.yml"
93
93
  - Gemfile
94
94
  - LICENSE.txt
95
95
  - README.md
96
96
  - Rakefile
97
+ - Vagrantfile
97
98
  - hypostasis.gemspec
98
99
  - lib/hypostasis.rb
99
100
  - lib/hypostasis/connection.rb
@@ -102,16 +103,21 @@ files:
102
103
  - lib/hypostasis/data_models/key_value.rb
103
104
  - lib/hypostasis/data_models/utilities.rb
104
105
  - lib/hypostasis/document.rb
106
+ - lib/hypostasis/document/belongs_to.rb
105
107
  - lib/hypostasis/document/fields.rb
106
108
  - lib/hypostasis/document/findable.rb
109
+ - lib/hypostasis/document/has_one.rb
107
110
  - lib/hypostasis/document/indexes.rb
111
+ - lib/hypostasis/document/namespaced.rb
108
112
  - lib/hypostasis/document/persistence.rb
109
113
  - lib/hypostasis/errors.rb
110
114
  - lib/hypostasis/key_path.rb
111
115
  - lib/hypostasis/namespace.rb
112
116
  - lib/hypostasis/tuple.rb
113
117
  - lib/hypostasis/version.rb
118
+ - provision.sh
114
119
  - test/connection_spec.rb
120
+ - test/document/has_one_spec.rb
115
121
  - test/document_spec.rb
116
122
  - test/key_path_spec.rb
117
123
  - test/minitest_helper.rb
@@ -129,22 +135,23 @@ require_paths:
129
135
  - lib
130
136
  required_ruby_version: !ruby/object:Gem::Requirement
131
137
  requirements:
132
- - - '>='
138
+ - - ">="
133
139
  - !ruby/object:Gem::Version
134
140
  version: '0'
135
141
  required_rubygems_version: !ruby/object:Gem::Requirement
136
142
  requirements:
137
- - - '>='
143
+ - - ">="
138
144
  - !ruby/object:Gem::Version
139
145
  version: '0'
140
146
  requirements: []
141
147
  rubyforge_project:
142
- rubygems_version: 2.1.11
148
+ rubygems_version: 2.2.1
143
149
  signing_key:
144
150
  specification_version: 4
145
151
  summary: A layer for FoundationDB providing multiple data models for Ruby.
146
152
  test_files:
147
153
  - test/connection_spec.rb
154
+ - test/document/has_one_spec.rb
148
155
  - test/document_spec.rb
149
156
  - test/key_path_spec.rb
150
157
  - test/minitest_helper.rb