hashy_db 0.0.1
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.
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.md +40 -0
- data/Rakefile +11 -0
- data/examples/guitar.rb +16 -0
- data/examples/guitar_document.rb +8 -0
- data/hashy_db.gemspec +25 -0
- data/lib/hashy_db/data_model.rb +147 -0
- data/lib/hashy_db/data_store.rb +84 -0
- data/lib/hashy_db/version.rb +3 -0
- data/lib/hashy_db.rb +2 -0
- data/spec/examples/guitar_document_spec.rb +17 -0
- data/spec/examples/guitar_spec.rb +32 -0
- data/spec/lib/data_store_spec.rb +75 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/examples/data_model_examples.rb +147 -0
- metadata +104 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@hashy_db --create
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Matt Simpson and Jason Mayer
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# What is this?
|
2
|
+
|
3
|
+
Provides an inteface to store and retrieve data in a Hash.
|
4
|
+
|
5
|
+
# Why would you want this?
|
6
|
+
|
7
|
+
- To defer choosing your database until you know most about your application.
|
8
|
+
- Provides assitance in designing a database agnostic architecture.
|
9
|
+
|
10
|
+
The hash can be loaded in memory and be used as your data store.
|
11
|
+
|
12
|
+
Example in a rails app:
|
13
|
+
|
14
|
+
initializers/datastore.rb
|
15
|
+
|
16
|
+
`ruby
|
17
|
+
::DB_HASH = {}
|
18
|
+
`
|
19
|
+
|
20
|
+
View the examples folder for an example implementation.
|
21
|
+
|
22
|
+
# Todos
|
23
|
+
|
24
|
+
- Make this into a gem
|
25
|
+
- Rename *.get_one into *.find
|
26
|
+
- Add a better readme
|
27
|
+
|
28
|
+
# Contribute
|
29
|
+
|
30
|
+
- fork into a topic branch, write specs, make a pull request.
|
31
|
+
|
32
|
+
# Owners
|
33
|
+
|
34
|
+
Matt Simpson - [@railsgrammer](https://twitter.com/railsgrammer)
|
35
|
+
<br />
|
36
|
+
Jason Mayer - [@farkerhaiku](https://twitter.com/farkerhaiku)
|
37
|
+
|
38
|
+
# Contributors
|
39
|
+
|
40
|
+
David Czarnecki - [@czarneckid](https://twitter.com/czarneckid)
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
6
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
7
|
+
spec.rspec_opts = ['--backtrace']
|
8
|
+
# spec.ruby_opts = ['-w']
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :spec
|
data/examples/guitar.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'guitar_document'
|
2
|
+
|
3
|
+
class Guitar
|
4
|
+
attr_reader :brand, :price, :type, :color, :id
|
5
|
+
|
6
|
+
def initialize(attrs)
|
7
|
+
@brand = attrs[:brand]
|
8
|
+
@price = attrs[:price]
|
9
|
+
@type = attrs[:type]
|
10
|
+
@color = attrs[:color]
|
11
|
+
end
|
12
|
+
|
13
|
+
def store
|
14
|
+
@id = GuitarDocument.store(self)
|
15
|
+
end
|
16
|
+
end
|
data/hashy_db.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'hashy_db/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "hashy_db"
|
7
|
+
s.version = HashyDB::VERSION
|
8
|
+
s.authors = ["Matt Simpson", "Jason Mayer"]
|
9
|
+
s.email = ["matt@railsgrammer.com", "jason.mayer@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/coffeencoke/HashyDB"
|
11
|
+
s.summary = %q{Provides an inteface to store and retrieve data in a Hash.}
|
12
|
+
s.description = %q{Provides an inteface to store and retrieve data in a Hash.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "hashy_db"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency('activesupport', '~> 3.1.3')
|
22
|
+
|
23
|
+
s.add_development_dependency('rake')
|
24
|
+
s.add_development_dependency('rspec')
|
25
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# SRP: Interface to read and write to and from the data store class for a specific collection
|
2
|
+
|
3
|
+
require_relative '../hashy_db/data_store'
|
4
|
+
|
5
|
+
require 'digest'
|
6
|
+
require 'active_support/concern'
|
7
|
+
|
8
|
+
module HashyDB
|
9
|
+
module DataModel
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
attr_reader :id, :model
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def data_fields(*fields)
|
18
|
+
create_data_fields(*fields) if fields.any?
|
19
|
+
@data_fields
|
20
|
+
end
|
21
|
+
|
22
|
+
def data_collection(collection_name = nil)
|
23
|
+
set_data_collection(collection_name) if collection_name
|
24
|
+
@data_collection
|
25
|
+
end
|
26
|
+
|
27
|
+
def store(model)
|
28
|
+
new(model).tap do |p|
|
29
|
+
p.add_to_data_store
|
30
|
+
end.id
|
31
|
+
end
|
32
|
+
|
33
|
+
def update(model)
|
34
|
+
new(model).tap do |p|
|
35
|
+
p.replace_in_data_store
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def remove_from_array(id, field, value)
|
40
|
+
HashyDB::DataStore.instance.remove_from_array(data_collection, :id, id, field, value)
|
41
|
+
end
|
42
|
+
|
43
|
+
def push_to_array(id, field, value)
|
44
|
+
HashyDB::DataStore.instance.push_to_array(data_collection, :id, id, field, value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_one(id)
|
48
|
+
HashyDB::DataStore.instance.get_one(data_collection, :id, id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def all
|
52
|
+
HashyDB::DataStore.instance.get(data_collection)
|
53
|
+
end
|
54
|
+
|
55
|
+
def all_by_field(field, value)
|
56
|
+
HashyDB::DataStore.instance.get_all_for_key_with_value(data_collection, field, value)
|
57
|
+
end
|
58
|
+
|
59
|
+
def all_by_fields(hash)
|
60
|
+
HashyDB::DataStore.instance.get_by_params(data_collection, hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
def find_by_fields(hash)
|
64
|
+
all_by_fields(hash).first
|
65
|
+
end
|
66
|
+
|
67
|
+
def containing_any(field, values)
|
68
|
+
HashyDB::DataStore.instance.containing_any(data_collection, field, values)
|
69
|
+
end
|
70
|
+
|
71
|
+
def array_contains(field, value)
|
72
|
+
HashyDB::DataStore.instance.array_contains(data_collection, field, value)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def set_data_collection(collection_name)
|
78
|
+
@data_collection = collection_name
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_data_fields(*fields)
|
82
|
+
attr_accessor *fields
|
83
|
+
@data_fields = fields
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def initialize(model)
|
88
|
+
@model = model
|
89
|
+
set_data_field_values
|
90
|
+
set_id
|
91
|
+
end
|
92
|
+
|
93
|
+
def data_fields
|
94
|
+
self.class.data_fields
|
95
|
+
end
|
96
|
+
|
97
|
+
def data_collection
|
98
|
+
self.class.data_collection
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_to_data_store
|
102
|
+
HashyDB::DataStore.instance.add(data_collection, attributes)
|
103
|
+
end
|
104
|
+
|
105
|
+
def replace_in_data_store
|
106
|
+
HashyDB::DataStore.instance.replace(data_collection, attributes)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def attributes
|
112
|
+
{ id: id }.merge(data_field_attributes)
|
113
|
+
end
|
114
|
+
|
115
|
+
def data_field_attributes
|
116
|
+
{}.tap do |hash|
|
117
|
+
data_fields.each do |field|
|
118
|
+
hash[field] = self.send(field)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def set_id
|
124
|
+
@id = if(model.respond_to?(:id) && model.id)
|
125
|
+
model.id
|
126
|
+
else
|
127
|
+
new_hash(Time.current)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def new_hash(salt)
|
132
|
+
Digest::SHA256.hexdigest("#{salt}#{model}")[0..6]
|
133
|
+
end
|
134
|
+
|
135
|
+
def set_data_field_values
|
136
|
+
data_fields.each { |field| set_data_field_value(field) }
|
137
|
+
end
|
138
|
+
|
139
|
+
def set_data_field_value(field)
|
140
|
+
self.send("#{field}=", model.send(field)) if field_exists?(field)
|
141
|
+
end
|
142
|
+
|
143
|
+
def field_exists?(field)
|
144
|
+
model.respond_to?(field) && !model.send(field).nil?
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# SRP: Model with implementation on how to store each collection in a data store
|
2
|
+
require 'singleton'
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
|
5
|
+
module HashyDB
|
6
|
+
class DataStore
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
attr_writer :data_store
|
10
|
+
|
11
|
+
def add(collection_name, hash)
|
12
|
+
get(collection_name) << hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def replace(collection_name, hash)
|
16
|
+
collection = get(collection_name)
|
17
|
+
index = collection.index{ |object| object[:id] == hash[:id] }
|
18
|
+
collection[index] = hash
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_all_for_key_with_value(collection_name, key, value)
|
22
|
+
get(collection_name).select { |a| a[key] == value }
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_by_params(collection_name, hash)
|
26
|
+
get(collection_name).select do |record|
|
27
|
+
hash.all?{|k,v| record[k] == v }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(collection_name)
|
32
|
+
data_store[collection_name] ||= []
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_one(collection_name, key, value)
|
36
|
+
get(collection_name).find { |x| x[key] == value }
|
37
|
+
end
|
38
|
+
|
39
|
+
def push_to_array(collection_name, identifying_key, identifying_value, array_key, value_to_push)
|
40
|
+
record = get_one(collection_name, identifying_key, identifying_value)
|
41
|
+
if (record[array_key])
|
42
|
+
record[array_key] << value_to_push
|
43
|
+
else
|
44
|
+
record[array_key] = [value_to_push]
|
45
|
+
end
|
46
|
+
record[array_key].uniq!
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove_from_array(collection_name, identifying_key, identifying_value, array_key, value_to_pop)
|
50
|
+
record = get_one(collection_name, identifying_key, identifying_value)
|
51
|
+
record[array_key].reject! { |x| x == value_to_pop }
|
52
|
+
end
|
53
|
+
|
54
|
+
def containing_any(collection_name, key, values)
|
55
|
+
get(collection_name).select do |x|
|
56
|
+
result = if x[key].is_a?(Array)
|
57
|
+
(x[key] & values).any?
|
58
|
+
else
|
59
|
+
values.include?(x[key])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def array_contains(collection_name, key, value)
|
65
|
+
get(collection_name).select do |x|
|
66
|
+
x[key] && x[key].include?(value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def clear
|
71
|
+
data_store.clear
|
72
|
+
end
|
73
|
+
|
74
|
+
def insert(collection_name, data)
|
75
|
+
data_store[collection_name] = data
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def data_store
|
81
|
+
@data_store ||= ::DB_HASH
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/hashy_db.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../../examples/guitar_document'
|
2
|
+
|
3
|
+
require_relative '../support/examples/data_model_examples'
|
4
|
+
|
5
|
+
describe GuitarDocument do
|
6
|
+
let(:collection_name) { :guitars }
|
7
|
+
let(:data_field_attributes) do
|
8
|
+
{
|
9
|
+
brand: 'a brand everyone knows',
|
10
|
+
price: 'a price you save up for',
|
11
|
+
type: 'the kind you want',
|
12
|
+
color: 'should be your favorite'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
it_behaves_like 'a data model'
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative '../../examples/guitar'
|
2
|
+
|
3
|
+
describe Guitar do
|
4
|
+
let(:attrs) { { brand: 'Gibson', price: 3399.99, type: 'Les Paul', color: 'Mahogany' } }
|
5
|
+
|
6
|
+
subject { described_class.new(attrs)}
|
7
|
+
|
8
|
+
its(:brand){ should == attrs[:brand] }
|
9
|
+
its(:price){ should == attrs[:price] }
|
10
|
+
its(:type){ should == attrs[:type] }
|
11
|
+
its(:color){ should == attrs[:color] }
|
12
|
+
|
13
|
+
describe "storing the guitar" do
|
14
|
+
let(:mock_id) { mock 'unique id for the guitar' }
|
15
|
+
|
16
|
+
before do
|
17
|
+
GuitarDocument.stub(store: mock_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'uses the guitar document to store it' do
|
21
|
+
GuitarDocument.should_receive(:store).with(subject).and_return(mock_id)
|
22
|
+
|
23
|
+
subject.store
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'sets the id received from the document to the guitar so we can find it later' do
|
27
|
+
subject.store
|
28
|
+
|
29
|
+
subject.id.should == mock_id
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative '../../lib/hashy_db/data_store'
|
2
|
+
|
3
|
+
describe HashyDB::DataStore do
|
4
|
+
subject { HashyDB::DataStore.instance }
|
5
|
+
|
6
|
+
let(:data1) { { id: 1, field_1: 'value 1', field_2: 3, field_3: [1,2,3], shared_between_1_and_2: 'awesome_value', :some_array => [1,2,3,4] } }
|
7
|
+
let(:data2) { { id: 2, field_1: 'value 1.2', field_2: 6, shared_between_1_and_2: 'awesome_value', :some_array => [4,5,6] } }
|
8
|
+
let(:data3) { { id: 3, field_1: 'value 3', field_2: 9, shared_between_1_and_2: 'not the same as 1 and 2', :some_array => [1,7] } }
|
9
|
+
|
10
|
+
before do
|
11
|
+
subject.data_store = {}
|
12
|
+
subject.insert(:some_collection, [data1, data2, data3])
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'can write and read data to and from a collection' do
|
16
|
+
data4 = { id: 3, field_1: 'value 3', field_2: 9, shared_between_1_and_2: 'not the same as 1 and 2', :some_array => [1,7] }
|
17
|
+
|
18
|
+
subject.add(:some_collection, data4)
|
19
|
+
subject.get(:some_collection).should == [data1, data2, data3, data4]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'can replace a record' do
|
23
|
+
data2[:field_1] = 'value modified'
|
24
|
+
subject.replace(:some_collection, data2)
|
25
|
+
|
26
|
+
subject.get_one(:some_collection, :id, 2)[:field_1].should == 'value modified'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can get one document' do
|
30
|
+
subject.get_one(:some_collection, :field_1, 'value 1').should == data1
|
31
|
+
subject.get_one(:some_collection, :field_2, 6).should == data2
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can clear the data store' do
|
35
|
+
subject.clear
|
36
|
+
|
37
|
+
subject.get(:some_collection).should == []
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can get all records of a specific key value' do
|
41
|
+
subject.get_all_for_key_with_value(:some_collection, :shared_between_1_and_2, 'awesome_value').should == [data1, data2]
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'can get all records where a value includes any of a set of values' do
|
45
|
+
subject.containing_any(:some_collection, :some_array, []).should == []
|
46
|
+
subject.containing_any(:some_collection, :some_array, [7, 2, 3]).should == [data1, data3]
|
47
|
+
subject.containing_any(:some_collection, :id, [1, 2, 5]).should == [data1, data2]
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can get all records where the array includes a value' do
|
51
|
+
subject.array_contains(:some_collection, :some_array, 1).should == [data1, data3]
|
52
|
+
subject.array_contains(:some_collection, :some_array_2, 1).should == []
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can push a value to an array for a specific record' do
|
56
|
+
subject.push_to_array(:some_collection, :id, 1, :field_3, 'add to existing array')
|
57
|
+
subject.push_to_array(:some_collection, :id, 1, :new_field, 'add to new array')
|
58
|
+
|
59
|
+
subject.get_one(:some_collection, :id, 1)[:field_3].should include('add to existing array')
|
60
|
+
subject.get_one(:some_collection, :id, 1)[:new_field].should == ['add to new array']
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can remove a value from an array for a specific record' do
|
64
|
+
subject.remove_from_array(:some_collection, :id, 1, :field_3, 2)
|
65
|
+
|
66
|
+
subject.get_one(:some_collection, :id, 1)[:field_3].should_not include(2)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'can get all records that match a given set of keys and values' do
|
70
|
+
records = subject.get_by_params(:some_collection, field_1: 'value 1', shared_between_1_and_2: 'awesome_value')
|
71
|
+
records.size.should be(1)
|
72
|
+
records.first[:id].should == 1
|
73
|
+
subject.get(:some_collection).size.should == 3
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require_relative '../../../lib/hashy_db/data_store'
|
3
|
+
|
4
|
+
shared_examples_for 'a data model' do
|
5
|
+
let(:mock_data_store) { mock 'data store data model' }
|
6
|
+
|
7
|
+
before do
|
8
|
+
HashyDB::DataStore.stub(:instance => mock_data_store)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "storing a data model" do
|
12
|
+
let(:current_time) { mock 'current time' }
|
13
|
+
let(:mock_data_model_string_rep) { mock 'data model string representation used for generating an id' }
|
14
|
+
let(:data_model_id) { full_data_model_id[0..6] }
|
15
|
+
let(:full_data_model_id) { '1234567891423456789' }
|
16
|
+
let(:mock_data_model) { mock 'a data model', data_field_attributes }
|
17
|
+
|
18
|
+
before do
|
19
|
+
Time.stub(:current => current_time)
|
20
|
+
Digest::SHA256.stub(:hexdigest => full_data_model_id)
|
21
|
+
mock_data_store.stub(:add)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'creates a unique hash for the id' do
|
25
|
+
Digest::SHA256.should_receive(:hexdigest).with("#{current_time}#{mock_data_model}").and_return(full_data_model_id)
|
26
|
+
|
27
|
+
described_class.store(mock_data_model)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'adds the data model to the db store' do
|
31
|
+
mock_data_store.should_receive(:add).with(collection_name, {id: data_model_id}.merge(data_field_attributes))
|
32
|
+
|
33
|
+
described_class.store(mock_data_model)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "updating a data model" do
|
38
|
+
let(:data_model_id) { '1234567' }
|
39
|
+
let(:mock_model) { mock 'a model', {:id => data_model_id}.merge(data_field_attributes) }
|
40
|
+
|
41
|
+
before do
|
42
|
+
mock_data_store.stub(:replace)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'replaces the data model in the db store' do
|
46
|
+
mock_data_store.should_receive(:replace).with(collection_name, {id: data_model_id}.merge(data_field_attributes))
|
47
|
+
|
48
|
+
described_class.update(mock_model)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "pushing a value to an array for a data model" do
|
53
|
+
let(:data_model_id) { '1234567' }
|
54
|
+
|
55
|
+
it 'replaces the data model in the db store' do
|
56
|
+
mock_data_store.should_receive(:push_to_array).with(collection_name, :id, data_model_id, :array_field, 'some value')
|
57
|
+
|
58
|
+
described_class.push_to_array(data_model_id, :array_field, 'some value')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "getting all data models with a specific value for a field" do
|
63
|
+
let(:mock_data_models) { mock 'data models in the data store' }
|
64
|
+
subject { described_class.array_contains(:some_field, 'some value') }
|
65
|
+
|
66
|
+
it 'returns the stored data models with the requested field / value' do
|
67
|
+
mock_data_store.should_receive(:array_contains).with(collection_name, :some_field, 'some value').and_return(mock_data_models)
|
68
|
+
|
69
|
+
subject.should == mock_data_models
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "removing a value from an array for a data model" do
|
74
|
+
let(:data_model_id) { '1234567' }
|
75
|
+
|
76
|
+
it 'removes the value from the array' do
|
77
|
+
mock_data_store.should_receive(:remove_from_array).with(collection_name, :id, data_model_id, :array_field, 'some value')
|
78
|
+
|
79
|
+
described_class.remove_from_array(data_model_id, :array_field, 'some value')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'getting all of the data models' do
|
84
|
+
let(:mock_data_models) { mock 'data models in the data store' }
|
85
|
+
|
86
|
+
it 'returns the stored data models' do
|
87
|
+
mock_data_store.should_receive(:get).with(collection_name).and_return(mock_data_models)
|
88
|
+
|
89
|
+
described_class.all.should == mock_data_models
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "getting all the data fields by a parameter hash" do
|
94
|
+
let(:mock_data_models) { mock 'some data model'}
|
95
|
+
let(:sample_hash) { {field1: nil, field2: 'not nil' }}
|
96
|
+
|
97
|
+
it 'passes the hash to the DataStore' do
|
98
|
+
mock_data_store.should_receive(:get_by_params).with(collection_name, sample_hash).and_return(mock_data_models)
|
99
|
+
|
100
|
+
described_class.all_by_fields(sample_hash).should == mock_data_models
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "getting a record by a set of key values" do
|
105
|
+
let(:mock_data_model) { mock 'some data model' }
|
106
|
+
let(:mock_data_models) { [mock_data_model]}
|
107
|
+
let(:sample_hash) { {field1: nil, field2: 'not nil' }}
|
108
|
+
|
109
|
+
it 'passes the hash to the DataStore' do
|
110
|
+
mock_data_store.should_receive(:get_by_params).with(collection_name, sample_hash).and_return(mock_data_models)
|
111
|
+
|
112
|
+
described_class.find_by_fields(sample_hash).should == mock_data_model
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "getting all of the data models for a where a field contains any value of a given array of values" do
|
117
|
+
let(:mock_data_models) { mock 'data models in the data store' }
|
118
|
+
subject { described_class.containing_any(:some_field, ['value 1', 'value 2']) }
|
119
|
+
|
120
|
+
it 'returns the stored data models' do
|
121
|
+
mock_data_store.should_receive(:containing_any).with(collection_name, :some_field, ['value 1', 'value 2']).and_return(mock_data_models)
|
122
|
+
|
123
|
+
subject.should == mock_data_models
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "getting all data models with a specific value for a field" do
|
128
|
+
let(:mock_data_models) { mock 'data models in the data store' }
|
129
|
+
subject { described_class.all_by_field(:some_field, 'some value') }
|
130
|
+
|
131
|
+
it 'returns the stored data models with the requested field / value' do
|
132
|
+
mock_data_store.should_receive(:get_all_for_key_with_value).with(collection_name, :some_field, 'some value').and_return(mock_data_models)
|
133
|
+
|
134
|
+
subject.should == mock_data_models
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'getting a specific data model' do
|
139
|
+
let(:mock_data_model) { mock 'data_model', :id => 'id' }
|
140
|
+
|
141
|
+
it 'returns the data model from the data store' do
|
142
|
+
mock_data_store.should_receive(:get_one).with(collection_name, :id, mock_data_model.id).and_return(mock_data_model)
|
143
|
+
|
144
|
+
described_class.get_one(mock_data_model.id).should == mock_data_model
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hashy_db
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matt Simpson
|
9
|
+
- Jason Mayer
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-02-02 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
requirement: &70126083361020 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.1.3
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70126083361020
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rake
|
28
|
+
requirement: &70126083360000 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70126083360000
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
requirement: &70126083359160 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70126083359160
|
48
|
+
description: Provides an inteface to store and retrieve data in a Hash.
|
49
|
+
email:
|
50
|
+
- matt@railsgrammer.com
|
51
|
+
- jason.mayer@gmail.com
|
52
|
+
executables: []
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- .gitignore
|
57
|
+
- .rspec
|
58
|
+
- .rvmrc
|
59
|
+
- Gemfile
|
60
|
+
- LICENSE.txt
|
61
|
+
- README.md
|
62
|
+
- Rakefile
|
63
|
+
- examples/guitar.rb
|
64
|
+
- examples/guitar_document.rb
|
65
|
+
- hashy_db.gemspec
|
66
|
+
- lib/hashy_db.rb
|
67
|
+
- lib/hashy_db/data_model.rb
|
68
|
+
- lib/hashy_db/data_store.rb
|
69
|
+
- lib/hashy_db/version.rb
|
70
|
+
- spec/examples/guitar_document_spec.rb
|
71
|
+
- spec/examples/guitar_spec.rb
|
72
|
+
- spec/lib/data_store_spec.rb
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/support/examples/data_model_examples.rb
|
75
|
+
homepage: https://github.com/coffeencoke/HashyDB
|
76
|
+
licenses: []
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project: hashy_db
|
95
|
+
rubygems_version: 1.8.10
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Provides an inteface to store and retrieve data in a Hash.
|
99
|
+
test_files:
|
100
|
+
- spec/examples/guitar_document_spec.rb
|
101
|
+
- spec/examples/guitar_spec.rb
|
102
|
+
- spec/lib/data_store_spec.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
- spec/support/examples/data_model_examples.rb
|