json_store 0.1.0 → 0.1.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 +4 -4
- data/.travis.yml +3 -0
- data/README.md +29 -0
- data/VERSION +1 -1
- data/json_store.gemspec +9 -5
- data/lib/json_store.rb +22 -15
- data/spec/json_store_spec.rb +141 -0
- data/spec/test_data/test1.json +1 -0
- data/spec/test_data/test2.json +1 -0
- data/spec/test_data/test3.json +1 -0
- metadata +7 -3
- data/Gemfile.lock +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfcfc3af69aa015556ac14133eaa9e7c73241017
|
4
|
+
data.tar.gz: ae79607a47bbc64c2548a4a834787dbe16f6a383
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1f1bb2d50d7529fd47ab19e3bc0d9d8886375b5dfff265b164920778866bb801dae03367f801156f396ee3502b8e2291649bc55df5d3ddd0f989c97d2f7b8b7
|
7
|
+
data.tar.gz: 689bc07143cd4b59f18344d82240fe8a90ba05fd306df36afc1ac91984311ac7f2a42d5e1d226ba323957ed7d9034e393eada766fd265150c8d4d259e8324794
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -21,6 +21,35 @@ db.merge
|
|
21
21
|
db.push
|
22
22
|
```
|
23
23
|
|
24
|
+
* Peristing more complex things like custom objects
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
|
28
|
+
class Person
|
29
|
+
|
30
|
+
def initialize(first,last)
|
31
|
+
@first = first
|
32
|
+
@last = last
|
33
|
+
end
|
34
|
+
|
35
|
+
def first
|
36
|
+
@first
|
37
|
+
end
|
38
|
+
|
39
|
+
def last
|
40
|
+
@last
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
db = JsonStore.new('people')
|
46
|
+
db.pull
|
47
|
+
db.set(:person,Person.new('Kingsley','Hendrickse'))
|
48
|
+
db.push
|
49
|
+
p db.get(:person).first # Kingsley
|
50
|
+
|
51
|
+
```
|
52
|
+
|
24
53
|
There are only a handful of commands:
|
25
54
|
|
26
55
|
* pull
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/json_store.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: json_store 0.1.
|
5
|
+
# stub: json_store 0.1.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "json_store"
|
9
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.1"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Kingsley Hendrickse"]
|
14
|
-
s.date = "2014-06-
|
14
|
+
s.date = "2014-06-23"
|
15
15
|
s.description = "A simple in memory key/value database using json that writes to file"
|
16
16
|
s.email = "kingsleyhendrickse@me.com"
|
17
17
|
s.extra_rdoc_files = [
|
@@ -20,14 +20,18 @@ Gem::Specification.new do |s|
|
|
20
20
|
]
|
21
21
|
s.files = [
|
22
22
|
".document",
|
23
|
+
".travis.yml",
|
23
24
|
"Gemfile",
|
24
|
-
"Gemfile.lock",
|
25
25
|
"LICENSE.txt",
|
26
26
|
"README.md",
|
27
27
|
"Rakefile",
|
28
28
|
"VERSION",
|
29
29
|
"json_store.gemspec",
|
30
|
-
"lib/json_store.rb"
|
30
|
+
"lib/json_store.rb",
|
31
|
+
"spec/json_store_spec.rb",
|
32
|
+
"spec/test_data/test1.json",
|
33
|
+
"spec/test_data/test2.json",
|
34
|
+
"spec/test_data/test3.json"
|
31
35
|
]
|
32
36
|
s.homepage = "http://github.com/kingsleyh/json_store"
|
33
37
|
s.licenses = ["MIT"]
|
data/lib/json_store.rb
CHANGED
@@ -21,12 +21,16 @@ class JsonStore
|
|
21
21
|
@map
|
22
22
|
end
|
23
23
|
|
24
|
+
def clear
|
25
|
+
@map = {}
|
26
|
+
end
|
27
|
+
|
24
28
|
def all_as_json
|
25
29
|
Oj.dump(@map)
|
26
30
|
end
|
27
31
|
|
28
|
-
def search(selector,kind=:matches)
|
29
|
-
JSONSelect(selector).send(kind
|
32
|
+
def search(selector, kind=:matches)
|
33
|
+
JSONSelect(selector).send(kind, @map)
|
30
34
|
end
|
31
35
|
|
32
36
|
def get_as_json(key)
|
@@ -35,7 +39,7 @@ class JsonStore
|
|
35
39
|
|
36
40
|
def pull
|
37
41
|
begin
|
38
|
-
@map =
|
42
|
+
@map = read_data
|
39
43
|
rescue LockMethod::Locked
|
40
44
|
sleep 0.5
|
41
45
|
pull
|
@@ -44,7 +48,7 @@ class JsonStore
|
|
44
48
|
|
45
49
|
def push
|
46
50
|
begin
|
47
|
-
|
51
|
+
write_data
|
48
52
|
rescue LockMethod::Locked
|
49
53
|
sleep 0.5
|
50
54
|
push
|
@@ -53,20 +57,24 @@ class JsonStore
|
|
53
57
|
|
54
58
|
def merge(direction=:into_remote)
|
55
59
|
begin
|
56
|
-
direction == :into_local ? @map.merge
|
60
|
+
@map = direction == :into_local ? @map.merge(read_data) : read_data.merge(@map)
|
57
61
|
rescue LockMethod::Locked
|
58
62
|
sleep 0.5
|
59
63
|
merge(direction)
|
60
64
|
end
|
61
65
|
end
|
62
66
|
|
63
|
-
def
|
64
|
-
|
67
|
+
def db_path
|
68
|
+
@db
|
65
69
|
end
|
66
70
|
|
67
71
|
private
|
68
72
|
|
69
|
-
def
|
73
|
+
def as_lock
|
74
|
+
'json_store'
|
75
|
+
end
|
76
|
+
|
77
|
+
def read_data
|
70
78
|
data = {}
|
71
79
|
if File.exists?(@db)
|
72
80
|
f = File.read(@db)
|
@@ -75,16 +83,15 @@ class JsonStore
|
|
75
83
|
data
|
76
84
|
end
|
77
85
|
|
78
|
-
lock_method :
|
86
|
+
lock_method :read_data
|
79
87
|
|
80
|
-
def
|
81
|
-
File.
|
88
|
+
def write_data
|
89
|
+
f = File.new(@db, 'w')
|
90
|
+
f.write(Oj.dump(@map))
|
91
|
+
f.close
|
82
92
|
end
|
83
93
|
|
84
|
-
lock_method :
|
94
|
+
lock_method :write_data
|
85
95
|
|
86
|
-
def keep_trying
|
87
|
-
|
88
|
-
end
|
89
96
|
|
90
97
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'fileutils'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/json_store'
|
4
|
+
|
5
|
+
describe JsonStore do
|
6
|
+
|
7
|
+
it 'should populate the memory map from file on pull' do
|
8
|
+
db = JsonStore.new(File.dirname(__FILE__) + '/test_data/test1.json')
|
9
|
+
db.pull
|
10
|
+
expect(db.all).to eq({'name' => 'Kingsley'})
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should create new db if none already exists during push' do
|
14
|
+
db = create_new_db('test2.json')
|
15
|
+
expect(File.exists?(db.db_path)).to eq(true)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should replace file with memory map on push overwriting same keys in file with map data' do
|
19
|
+
db = create_new_db('test2.json')
|
20
|
+
expect(db.all).to eq({name: 'Kingsley'})
|
21
|
+
db.set(:name, 'Kostas')
|
22
|
+
db.set(:slot, 'PM')
|
23
|
+
db.push
|
24
|
+
db.pull
|
25
|
+
expect(db.all).to eq({name: 'Kostas', slot: 'PM'})
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should merge memory map changes into file on merge into_remote' do
|
29
|
+
db = create_new_db('test2.json')
|
30
|
+
expect(db.all).to eq({name: 'Kingsley'})
|
31
|
+
db.set(:name, 'Kostas')
|
32
|
+
db.set(:slot, 'PM')
|
33
|
+
db.merge
|
34
|
+
expect(db.all).to eq({name: 'Kostas', slot: 'PM'})
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should merge file changes into memory map on merge into_local' do
|
38
|
+
db = create_new_db('test2.json')
|
39
|
+
expect(db.all).to eq({name: 'Kingsley'})
|
40
|
+
db.set(:name, 'Kostas')
|
41
|
+
db.set(:slot, 'PM')
|
42
|
+
db.merge(:into_local)
|
43
|
+
expect(db.all).to eq({name: 'Kingsley', slot: 'PM'})
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should get value by by key of stored items' do
|
47
|
+
db = JsonStore.new(File.dirname(__FILE__) + '/test_data/test1.json')
|
48
|
+
db.pull
|
49
|
+
expect(db.get('name')).to eq('Kingsley')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should return json on get_as_json' do
|
53
|
+
db = JsonStore.new(File.dirname(__FILE__) + '/test_data/test1.json')
|
54
|
+
db.pull
|
55
|
+
expect(db.get_as_json('name')).to eq('"Kingsley"')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should return json on all_as_json' do
|
59
|
+
db = JsonStore.new(File.dirname(__FILE__) + '/test_data/test1.json')
|
60
|
+
db.pull
|
61
|
+
expect(db.all_as_json).to eq('{"name":"Kingsley"}')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should search basic json structure using json select' do
|
65
|
+
db = create_new_db('test2.json', {people: [{first_name: 'Kingsley', last_name: 'Hendrickse'}, {first_name: 'Kostas', last_name: 'Mamalis'}]})
|
66
|
+
expect(db.search('.people .first_name')).to eq(['Kingsley', 'Kostas'])
|
67
|
+
expect(db.search('.people .first_name', :match)).to eq('Kingsley')
|
68
|
+
expect(db.search('.people .first_name', :test)).to eq(true)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should be able to store a more complex object' do
|
72
|
+
class Person;
|
73
|
+
attr_accessor :first_name, :last_name;
|
74
|
+
|
75
|
+
def initialize(name)
|
76
|
+
; d = name.split(' '); @first_name = d.first; @last_name = d.last;
|
77
|
+
end
|
78
|
+
|
79
|
+
;
|
80
|
+
end
|
81
|
+
db = create_new_db('test2.json', {people: [Person.new('Kingsley Hendrickse'), Person.new('Kostas Mamalis')]})
|
82
|
+
expect(db.get(:people).map { |person| person.first_name }).to eq(['Kingsley', 'Kostas'])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should clear the in memory map' do
|
86
|
+
db = create_new_db('test2.json')
|
87
|
+
db.clear
|
88
|
+
expect(db.all).to eq({})
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should work with simple scenario' do
|
92
|
+
db = create_new_db('test2.json')
|
93
|
+
data = {day: 'Mon', year: '2014'}
|
94
|
+
db.set(:date, data)
|
95
|
+
db.push
|
96
|
+
expect(db.get(:date)).to eq(data)
|
97
|
+
db2 = JsonStore.new(File.dirname(__FILE__) + '/test_data/test2.json')
|
98
|
+
db2.pull
|
99
|
+
db2.set(:slot, 'PM')
|
100
|
+
db2.push
|
101
|
+
db.merge
|
102
|
+
expect(db.all).to eq(name: 'Kingsley', date: {day: 'Mon', year: '2014'}, slot: 'PM')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should lock to prevent concurrent access' do
|
106
|
+
t1 = Thread.new {
|
107
|
+
20.times{
|
108
|
+
db = create_new_db('test3.json')
|
109
|
+
db.set(:slot, "1_PM")
|
110
|
+
db.merge
|
111
|
+
db.push
|
112
|
+
}
|
113
|
+
}
|
114
|
+
t2 = Thread.new {
|
115
|
+
20.times {
|
116
|
+
db = create_new_db('test3.json')
|
117
|
+
db.set(:slot, "2_PM")
|
118
|
+
db.merge
|
119
|
+
db.push
|
120
|
+
}
|
121
|
+
}
|
122
|
+
t2.join
|
123
|
+
t1.join
|
124
|
+
db2 = JsonStore.new(File.dirname(__FILE__) + '/test_data/test3.json')
|
125
|
+
db2.pull
|
126
|
+
expect(db2.get(:slot)).to match(/PM/)
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def create_new_db(path, content={name: 'Kingsley'})
|
133
|
+
file_path = File.dirname(__FILE__) + "/test_data/#{path}"
|
134
|
+
FileUtils.rm_rf(file_path)
|
135
|
+
db = JsonStore.new(file_path)
|
136
|
+
db.set(content.keys.first, content[content.keys.first])
|
137
|
+
db.push
|
138
|
+
db
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"name":"Kingsley"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{":name":"Kingsley",":date":{":day":"Mon",":year":"2014"},":slot":"PM"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{":name":"Kingsley",":slot":"1_PM"}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kingsley Hendrickse
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -103,14 +103,18 @@ extra_rdoc_files:
|
|
103
103
|
- README.md
|
104
104
|
files:
|
105
105
|
- ".document"
|
106
|
+
- ".travis.yml"
|
106
107
|
- Gemfile
|
107
|
-
- Gemfile.lock
|
108
108
|
- LICENSE.txt
|
109
109
|
- README.md
|
110
110
|
- Rakefile
|
111
111
|
- VERSION
|
112
112
|
- json_store.gemspec
|
113
113
|
- lib/json_store.rb
|
114
|
+
- spec/json_store_spec.rb
|
115
|
+
- spec/test_data/test1.json
|
116
|
+
- spec/test_data/test2.json
|
117
|
+
- spec/test_data/test3.json
|
114
118
|
homepage: http://github.com/kingsleyh/json_store
|
115
119
|
licenses:
|
116
120
|
- MIT
|
data/Gemfile.lock
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
activesupport (4.1.1)
|
5
|
-
i18n (~> 0.6, >= 0.6.9)
|
6
|
-
json (~> 1.7, >= 1.7.7)
|
7
|
-
minitest (~> 5.1)
|
8
|
-
thread_safe (~> 0.1)
|
9
|
-
tzinfo (~> 1.1)
|
10
|
-
addressable (2.3.6)
|
11
|
-
builder (3.2.2)
|
12
|
-
cache (0.4.0)
|
13
|
-
descendants_tracker (0.0.4)
|
14
|
-
thread_safe (~> 0.3, >= 0.3.1)
|
15
|
-
diff-lcs (1.2.5)
|
16
|
-
faraday (0.9.0)
|
17
|
-
multipart-post (>= 1.2, < 3)
|
18
|
-
git (1.2.7)
|
19
|
-
github_api (0.11.3)
|
20
|
-
addressable (~> 2.3)
|
21
|
-
descendants_tracker (~> 0.0.1)
|
22
|
-
faraday (~> 0.8, < 0.10)
|
23
|
-
hashie (>= 1.2)
|
24
|
-
multi_json (>= 1.7.5, < 2.0)
|
25
|
-
nokogiri (~> 1.6.0)
|
26
|
-
oauth2
|
27
|
-
hashie (3.0.0)
|
28
|
-
highline (1.6.21)
|
29
|
-
i18n (0.6.9)
|
30
|
-
jeweler (2.0.1)
|
31
|
-
builder
|
32
|
-
bundler (>= 1.0)
|
33
|
-
git (>= 1.2.5)
|
34
|
-
github_api
|
35
|
-
highline (>= 1.6.15)
|
36
|
-
nokogiri (>= 1.5.10)
|
37
|
-
rake
|
38
|
-
rdoc
|
39
|
-
json (1.8.1)
|
40
|
-
json_select (0.1.4)
|
41
|
-
treetop
|
42
|
-
jwt (1.0.0)
|
43
|
-
lock_method (0.5.5)
|
44
|
-
activesupport
|
45
|
-
cache (>= 0.2.1)
|
46
|
-
mini_portile (0.6.0)
|
47
|
-
minitest (5.3.5)
|
48
|
-
multi_json (1.10.1)
|
49
|
-
multi_xml (0.5.5)
|
50
|
-
multipart-post (2.0.0)
|
51
|
-
nokogiri (1.6.2.1)
|
52
|
-
mini_portile (= 0.6.0)
|
53
|
-
oauth2 (0.9.4)
|
54
|
-
faraday (>= 0.8, < 0.10)
|
55
|
-
jwt (~> 1.0)
|
56
|
-
multi_json (~> 1.3)
|
57
|
-
multi_xml (~> 0.5)
|
58
|
-
rack (~> 1.2)
|
59
|
-
oj (2.9.6)
|
60
|
-
polyglot (0.3.5)
|
61
|
-
rack (1.5.2)
|
62
|
-
rake (10.3.2)
|
63
|
-
rdoc (4.1.1)
|
64
|
-
json (~> 1.4)
|
65
|
-
rspec (3.0.0)
|
66
|
-
rspec-core (~> 3.0.0)
|
67
|
-
rspec-expectations (~> 3.0.0)
|
68
|
-
rspec-mocks (~> 3.0.0)
|
69
|
-
rspec-core (3.0.1)
|
70
|
-
rspec-support (~> 3.0.0)
|
71
|
-
rspec-expectations (3.0.1)
|
72
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
73
|
-
rspec-support (~> 3.0.0)
|
74
|
-
rspec-mocks (3.0.1)
|
75
|
-
rspec-support (~> 3.0.0)
|
76
|
-
rspec-support (3.0.0)
|
77
|
-
thread_safe (0.3.4)
|
78
|
-
treetop (1.5.3)
|
79
|
-
polyglot (~> 0.3)
|
80
|
-
tzinfo (1.2.1)
|
81
|
-
thread_safe (~> 0.1)
|
82
|
-
|
83
|
-
PLATFORMS
|
84
|
-
ruby
|
85
|
-
|
86
|
-
DEPENDENCIES
|
87
|
-
bundler (~> 1.0)
|
88
|
-
jeweler (~> 2.0.1)
|
89
|
-
json_select
|
90
|
-
lock_method
|
91
|
-
oj
|
92
|
-
rspec (~> 3.0.0.rc1)
|