hypostasis 0.2.1 → 0.2.2

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