hikki 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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +98 -0
- data/Rakefile +6 -0
- data/adapters/hikki-memcache/.rspec +2 -0
- data/adapters/hikki-memcache/.travis.yml +3 -0
- data/adapters/hikki-memcache/Gemfile +7 -0
- data/adapters/hikki-memcache/LICENSE.txt +22 -0
- data/adapters/hikki-memcache/README.md +50 -0
- data/adapters/hikki-memcache/Rakefile +6 -0
- data/adapters/hikki-memcache/hikki-memcache.gemspec +27 -0
- data/adapters/hikki-memcache/lib/hikki/adapters/memcache_adapter.rb +22 -0
- data/adapters/hikki-memcache/lib/hikki/adapters/memcache_collection.rb +54 -0
- data/adapters/hikki-memcache/spec/hikki/adapters/memcache_adapter_integration_spec.rb +39 -0
- data/adapters/hikki-memcache/spec/hikki/adapters/memcache_adapter_spec.rb +115 -0
- data/adapters/hikki-memcache/spec/spec_helper.rb +8 -0
- data/adapters/hikki-mongo/.rspec +2 -0
- data/adapters/hikki-mongo/.travis.yml +3 -0
- data/adapters/hikki-mongo/Gemfile +7 -0
- data/adapters/hikki-mongo/LICENSE.txt +22 -0
- data/adapters/hikki-mongo/README.md +44 -0
- data/adapters/hikki-mongo/Rakefile +6 -0
- data/adapters/hikki-mongo/hikki-mongo.gemspec +28 -0
- data/adapters/hikki-mongo/lib/hikki/adapters/mongo_adapter.rb +22 -0
- data/adapters/hikki-mongo/lib/hikki/adapters/mongo_collection.rb +86 -0
- data/adapters/hikki-mongo/spec/hikki/adapters/mongo_adapter_integration_spec.rb +39 -0
- data/adapters/hikki-mongo/spec/hikki/adapters/mongo_adapter_spec.rb +231 -0
- data/adapters/hikki-mongo/spec/spec_helper.rb +8 -0
- data/adapters/hikki-redis/.rspec +2 -0
- data/adapters/hikki-redis/.travis.yml +3 -0
- data/adapters/hikki-redis/Gemfile +7 -0
- data/adapters/hikki-redis/LICENSE.txt +22 -0
- data/adapters/hikki-redis/README.md +44 -0
- data/adapters/hikki-redis/Rakefile +6 -0
- data/adapters/hikki-redis/hikki-redis.gemspec +27 -0
- data/adapters/hikki-redis/lib/hikki/adapters/redis_adapter.rb +21 -0
- data/adapters/hikki-redis/lib/hikki/adapters/redis_collection.rb +105 -0
- data/adapters/hikki-redis/spec/hikki/adapters/redis_adapter_integration_spec.rb +39 -0
- data/adapters/hikki-redis/spec/hikki/adapters/redis_adapter_spec.rb +258 -0
- data/adapters/hikki-redis/spec/spec_helper.rb +8 -0
- data/all_specs +13 -0
- data/hikki.gemspec +24 -0
- data/lib/hikki.rb +9 -0
- data/lib/hikki/adapters/adapter.rb +43 -0
- data/lib/hikki/adapters/memory_adapter.rb +18 -0
- data/lib/hikki/adapters/memory_collection.rb +87 -0
- data/lib/hikki/collection.rb +62 -0
- data/lib/hikki/repository.rb +54 -0
- data/lib/hikki/version.rb +3 -0
- data/spec/hikki/adapters/memory_adapter_spec.rb +242 -0
- data/spec/hikki/repository_spec.rb +260 -0
- data/spec/hikki_spec.rb +5 -0
- data/spec/spec_helper.rb +2 -0
- metadata +146 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'hikki/adapters/redis_adapter'
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
5
|
+
config.run_all_when_everything_filtered = true
|
6
|
+
config.filter_run :focus
|
7
|
+
config.filter_run_excluding :integration
|
8
|
+
end
|
data/all_specs
ADDED
data/hikki.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hikki/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'hikki'
|
8
|
+
spec.version = Hikki::VERSION
|
9
|
+
spec.authors = ['alexpeachey']
|
10
|
+
spec.email = ['alex.peachey@originate.com']
|
11
|
+
spec.summary = 'A light weight persistence system.'
|
12
|
+
spec.description = 'A light weight persistence system.'
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
end
|
data/lib/hikki.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Hikki
|
2
|
+
module Adapters
|
3
|
+
class Adapter
|
4
|
+
attr_reader :collections
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@collections = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def index(collection, field)
|
11
|
+
collection_for(collection).index(field)
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(collection, data)
|
15
|
+
collection_for(collection).save(data)
|
16
|
+
end
|
17
|
+
|
18
|
+
def find(collection, id)
|
19
|
+
collection_for(collection).find(id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def all(collection, options={})
|
23
|
+
collection_for(collection).all(options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_by(collection, field, value, options={})
|
27
|
+
collection_for(collection).find_by(field, value, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove(collection, id)
|
31
|
+
collection_for(collection).remove(id)
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove_all(collection)
|
35
|
+
collection_for(collection).remove_all
|
36
|
+
end
|
37
|
+
|
38
|
+
def collection_for(collection)
|
39
|
+
collections.fetch(collection, Collection.new(collection, store, uuid_generator))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Hikki
|
2
|
+
module Adapters
|
3
|
+
class MemoryAdapter < Hikki::Adapters::Adapter
|
4
|
+
attr_reader :store, :uuid_generator, :collections
|
5
|
+
|
6
|
+
def initialize(uuid_generator=SecureRandom)
|
7
|
+
super()
|
8
|
+
@uuid_generator = uuid_generator
|
9
|
+
@store = {}
|
10
|
+
@collections = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def collection_for(collection)
|
14
|
+
collections.fetch(collection, MemoryCollection.new(collection, store, uuid_generator))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Hikki
|
2
|
+
module Adapters
|
3
|
+
class MemoryCollection < Hikki::Collection
|
4
|
+
attr_reader :store, :uuid_generator
|
5
|
+
|
6
|
+
def initialize(collection, store, uuid_generator)
|
7
|
+
super(collection)
|
8
|
+
@store = store
|
9
|
+
@uuid_generator = uuid_generator
|
10
|
+
end
|
11
|
+
|
12
|
+
def index(field)
|
13
|
+
store[index_key] ||= {}
|
14
|
+
store[index_key][field.to_s] ||= {}
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def save(data)
|
19
|
+
data = normalize_data(data)
|
20
|
+
store[collection] ||= {}
|
21
|
+
store[collection][data['id']] = data
|
22
|
+
add_to_index(data)
|
23
|
+
data
|
24
|
+
end
|
25
|
+
|
26
|
+
def find(id)
|
27
|
+
store.fetch(collection, {}).fetch(id.to_s, {})
|
28
|
+
end
|
29
|
+
|
30
|
+
def all(options={})
|
31
|
+
options = normalize_options(options)
|
32
|
+
store.fetch(collection, {}).values[page_range(options)]
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_by(field, value, options={})
|
36
|
+
options = normalize_options(options)
|
37
|
+
return find_by_index(field, value, options) if has_index?(field)
|
38
|
+
all.select { |o| o.fetch(field.to_s) == value }[page_range(options)]
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove(id)
|
42
|
+
remove_from_index(find(id))
|
43
|
+
store.fetch(collection, {}).delete(id.to_s)
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def remove_all
|
48
|
+
store.delete(collection)
|
49
|
+
store.delete(index_key)
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def has_index?(field)
|
54
|
+
store.has_key?(index_key) &&
|
55
|
+
store[index_key].has_key?(field.to_s)
|
56
|
+
end
|
57
|
+
|
58
|
+
def id_for(data)
|
59
|
+
data.fetch('id', uuid_generator.uuid).to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def index_key
|
64
|
+
collection + '_index'
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_by_index(field, value, options)
|
68
|
+
store[index_key][field.to_s].fetch(value, []).map { |id| find(id) }.reject { |v| v == {} }[page_range(options)]
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_to_index(data)
|
72
|
+
store.fetch(index_key, {}).keys.each do |field|
|
73
|
+
store[index_key][field][data[field]] ||= []
|
74
|
+
store[index_key][field][data[field]] << data['id']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def remove_from_index(data)
|
79
|
+
return if data == {}
|
80
|
+
store.fetch(index_key, {}).keys.each do |field|
|
81
|
+
store[index_key][field].fetch(data[field], []).delete(data['id'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Hikki
|
4
|
+
class Collection
|
5
|
+
attr_reader :collection
|
6
|
+
|
7
|
+
def initialize(collection)
|
8
|
+
@collection = collection.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def index(field)
|
12
|
+
raise 'Implementation missing.'
|
13
|
+
end
|
14
|
+
|
15
|
+
def save(data)
|
16
|
+
raise 'Implementation missing.'
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(id)
|
20
|
+
raise 'Implementation missing.'
|
21
|
+
end
|
22
|
+
|
23
|
+
def all(options)
|
24
|
+
raise 'Implementation missing.'
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_by(field, value, options)
|
28
|
+
raise 'Implementation missing.'
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove(id)
|
32
|
+
raise 'Implementation missing.'
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove_all
|
36
|
+
raise 'Implementation missing.'
|
37
|
+
end
|
38
|
+
|
39
|
+
def normalize_data(data)
|
40
|
+
deep_copy(data).tap { |d| d.merge!('id' => id_for(d)) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def deep_copy(h)
|
44
|
+
JSON.parse(h.to_json)
|
45
|
+
end
|
46
|
+
|
47
|
+
def id_for(data)
|
48
|
+
data.fetch('id', 'undefined').to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
def normalize_options(options)
|
52
|
+
{
|
53
|
+
limit: options[:limit] || options['limit'] || -1,
|
54
|
+
offset: options[:offset] || options['offset'] || 0
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def page_range(options)
|
59
|
+
(options[:offset]..(options[:limit] == -1 ? -1 : options[:offset] + options[:limit] - 1))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Hikki
|
2
|
+
class Repository
|
3
|
+
|
4
|
+
attr_reader :writers, :readers
|
5
|
+
|
6
|
+
def initialize(writers=[], readers=[])
|
7
|
+
@writers = Array(writers)
|
8
|
+
@writers << Hikki::Adapters::MemoryAdapter.new if @writers == []
|
9
|
+
@readers = Array(readers)
|
10
|
+
@readers << @writers.first if @readers == []
|
11
|
+
end
|
12
|
+
|
13
|
+
def save(collection, data)
|
14
|
+
writers.reduce({}) { |result, writer| writer.save(collection, data) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def index(collection, field)
|
18
|
+
writers.all? { |writer| writer.index(collection, field) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def remove(collection, field)
|
22
|
+
writers.all? { |writer| writer.remove(collection, field) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_all(collection)
|
26
|
+
writers.all? { |writer| writer.remove_all(collection) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def find(collection, id)
|
30
|
+
readers.each do |reader|
|
31
|
+
result = reader.find(collection, id)
|
32
|
+
return result unless result == {}
|
33
|
+
end
|
34
|
+
{}
|
35
|
+
end
|
36
|
+
|
37
|
+
def all(collection, options={})
|
38
|
+
readers.each do |reader|
|
39
|
+
result = reader.all(collection, options)
|
40
|
+
return result unless result == []
|
41
|
+
end
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_by(collection, field, value, options={})
|
46
|
+
readers.each do |reader|
|
47
|
+
result = reader.find_by(collection, field, value, options)
|
48
|
+
return result unless result == []
|
49
|
+
end
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Hikki
|
4
|
+
module Adapters
|
5
|
+
describe MemoryAdapter do
|
6
|
+
subject(:adapter) { MemoryAdapter.new(uuid_generator) }
|
7
|
+
let(:uuid_generator) { double :generator, uuid: '12345' }
|
8
|
+
let(:collection) { 'collection1' }
|
9
|
+
|
10
|
+
describe '#index' do
|
11
|
+
it 'returns true' do
|
12
|
+
expect(adapter.index(collection, :field1)).to be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'creates the index in the store' do
|
16
|
+
adapter.index(collection, :field1)
|
17
|
+
expect(adapter.store['collection1_index']['field1']).to eq Hash.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#save' do
|
22
|
+
context 'when an id is provided in the data' do
|
23
|
+
let(:data) { { id: id, field1: 'test', field2: 123 } }
|
24
|
+
let(:expected) { { 'id' => id, 'field1' => 'test', 'field2' => 123 } }
|
25
|
+
let(:id) { '1' }
|
26
|
+
|
27
|
+
it 'returns the data' do
|
28
|
+
expect(adapter.save(collection, data)).to eq expected
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'persists the data in the store' do
|
32
|
+
adapter.save(collection, data)
|
33
|
+
expect(adapter.store['collection1']['1']).to eq expected
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when an id is not provided in the data' do
|
38
|
+
let(:data) { { field1: 'test', field2: 123 } }
|
39
|
+
let(:expected) { { 'id' => id, 'field1' => 'test', 'field2' => 123 } }
|
40
|
+
let(:id) { '12345' }
|
41
|
+
|
42
|
+
it 'returns the data with the id added' do
|
43
|
+
expect(adapter.save(collection, data)).to eq expected
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'persists the data in the store' do
|
47
|
+
adapter.save(collection, data)
|
48
|
+
expect(adapter.store['collection1']['12345']).to eq expected
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when an index exists on a field in the data' do
|
53
|
+
let(:data) { { id: id, field1: 'test', field2: 123 } }
|
54
|
+
let(:expected) { { 'id' => id, 'field1' => 'test', 'field2' => 123 } }
|
55
|
+
let(:id) { '1' }
|
56
|
+
before { adapter.index(collection, :field1) }
|
57
|
+
|
58
|
+
it 'adds an entry in the index' do
|
59
|
+
adapter.save(collection, data)
|
60
|
+
expect(adapter.store['collection1_index']['field1']['test']).to eq ['1']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#find' do
|
66
|
+
let(:id) { '1' }
|
67
|
+
|
68
|
+
context 'when the id exists' do
|
69
|
+
let(:data) { { id: id, field1: 'test', field2: 123 } }
|
70
|
+
let(:expected) { { 'id' => id, 'field1' => 'test', 'field2' => 123 } }
|
71
|
+
before { adapter.save(collection, data) }
|
72
|
+
|
73
|
+
it 'retrieves the data' do
|
74
|
+
expect(adapter.find(collection, id)).to eq expected
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when the id does not exist' do
|
79
|
+
let(:expected) { {} }
|
80
|
+
|
81
|
+
it 'returns an empty hash' do
|
82
|
+
expect(adapter.find(collection, id)).to eq expected
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#all' do
|
88
|
+
context 'with a record in the collection' do
|
89
|
+
let(:data) { { id: '1', field1: 'test', field2: 123 } }
|
90
|
+
let(:expected) { { 'id' => '1', 'field1' => 'test', 'field2' => 123 } }
|
91
|
+
before { adapter.save(collection, data) }
|
92
|
+
|
93
|
+
it 'returns an array containing the record' do
|
94
|
+
expect(adapter.all(collection)).to eq [expected]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with no records in the collection' do
|
99
|
+
it 'returns an array containing the record' do
|
100
|
+
expect(adapter.all(collection)).to eq []
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'with multiple records and paging options specified' do
|
105
|
+
before do
|
106
|
+
10.times do |i|
|
107
|
+
adapter.save(collection, {id: i+1, a: 1})
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with limit 2' do
|
112
|
+
let(:limit) { 2 }
|
113
|
+
|
114
|
+
it 'returns only 2 records' do
|
115
|
+
expect(adapter.all(collection, {limit: 2}).count).to eq 2
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'with an offset of 4' do
|
119
|
+
it 'returns the 2 records starting with the offset' do
|
120
|
+
expect(adapter.all(collection, {limit: 2, offset: 4})).to eq [{'id' => '5', 'a' => 1}, {'id' => '6', 'a' => 1}]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#find_by' do
|
128
|
+
context 'with a record in the collection matching' do
|
129
|
+
let(:data) { { id: '1', field1: 'test', field2: 123 } }
|
130
|
+
let(:expected) { { 'id' => '1', 'field1' => 'test', 'field2' => 123 } }
|
131
|
+
|
132
|
+
context 'without an index' do
|
133
|
+
before { adapter.save(collection, data) }
|
134
|
+
|
135
|
+
it 'returns an array containing the record' do
|
136
|
+
expect(adapter.find_by(collection, :field2, 123)).to eq [expected]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with an index' do
|
141
|
+
before do
|
142
|
+
adapter.index(collection, :field1)
|
143
|
+
adapter.save(collection, data)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'returns an array containing the record' do
|
147
|
+
expect(adapter.find_by(collection, :field1, 'test')).to eq [expected]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'with no matching records in the collection' do
|
153
|
+
it 'returns an array containing the record' do
|
154
|
+
expect(adapter.find_by(collection, :field1, 'foo')).to eq []
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'with multiple matching records and paging options specified' do
|
159
|
+
before do
|
160
|
+
10.times do |i|
|
161
|
+
adapter.save(collection, {id: i+1, a: 1})
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'with limit 2' do
|
166
|
+
let(:limit) { 2 }
|
167
|
+
|
168
|
+
it 'returns only 2 records' do
|
169
|
+
expect(adapter.find_by(collection, :a, 1, {limit: 2}).count).to eq 2
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with an offset of 4' do
|
173
|
+
it 'returns the 2 records starting with the offset' do
|
174
|
+
expect(adapter.find_by(collection, :a, 1, {limit: 2, offset: 4})).to eq [{'id' => '5', 'a' => 1}, {'id' => '6', 'a' => 1}]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '#remove' do
|
182
|
+
context 'with a record for the id in the collection' do
|
183
|
+
let(:data) { { id: id, field1: 'test', field2: 123 } }
|
184
|
+
let(:id) { '1' }
|
185
|
+
before { adapter.save(collection, data) }
|
186
|
+
|
187
|
+
it 'returns true' do
|
188
|
+
expect(adapter.remove(collection, id)).to be_true
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'removes the record from the store' do
|
192
|
+
adapter.remove(collection, id)
|
193
|
+
expect(adapter.store[collection][id]).to be_nil
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'when there is an index' do
|
197
|
+
before do
|
198
|
+
adapter.index(collection, :field1)
|
199
|
+
adapter.save(collection, data)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'removes the id from the index' do
|
203
|
+
expect(adapter.store[collection + '_index']['field1']['test']).to eq ['1']
|
204
|
+
adapter.remove(collection, id)
|
205
|
+
expect(adapter.store[collection + '_index']['field1']['test']).to eq []
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe '#remove_all' do
|
212
|
+
context 'with a record in the collection' do
|
213
|
+
let(:data) { { id: id, field1: 'test', field2: 123 } }
|
214
|
+
let(:id) { '1' }
|
215
|
+
before { adapter.save(collection, data) }
|
216
|
+
|
217
|
+
it 'returns true' do
|
218
|
+
expect(adapter.remove_all(collection)).to be_true
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'removes all records from the store' do
|
222
|
+
adapter.remove_all(collection)
|
223
|
+
expect(adapter.store[collection]).to be_nil
|
224
|
+
end
|
225
|
+
|
226
|
+
context 'when there is an index' do
|
227
|
+
before do
|
228
|
+
adapter.index(collection, :field1)
|
229
|
+
adapter.save(collection, data)
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'removes the id from the index' do
|
233
|
+
expect(adapter.store[collection + '_index']['field1']['test']).to eq ['1']
|
234
|
+
adapter.remove_all(collection)
|
235
|
+
expect(adapter.store[collection + '_index']).to be_nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|