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